微信小程序授权登录逻辑实现

0 阅读4分钟

微信小程序授权登录逻辑实现

微信小程序的授权登录是连接用户与后端服务的关键流程。一个健壮、安全的授权逻辑不仅能提升用户体验,也是数据安全的基础。本文将详细介绍其标准实现流程、核心代码、常见陷阱及最佳实践。

1. 核心实现逻辑与代码示例

微信小程序授权登录主要分为前端获取用户凭证、后端验证并建立会话两大步骤。

1.1 前端流程

前端主要负责引导用户授权并获取临时凭证 code

// pages/login/login.js
Page({
  handleLogin: function() {
    // 1. 检查用户是否已授权
    wx.getSetting({
      success: (res) => {
        if (res.authSetting['scope.userInfo']) {
          // 已授权,直接获取用户信息并登录
          this.getUserInfoAndLogin();
        } else {
          // 未授权,显示授权按钮(由 button 组件触发)
          // 或者使用 wx.authorize 提前发起授权(部分 scope 需要)
          // 对于 userInfo,通常由 button 触发
        }
      }
    });
  },

  // 由页面上的 <button open-type="getUserInfo"> 触发
  onGetUserInfo: function(e) {
    if (e.detail.userInfo) {
      // 用户点击了“允许”
      const userInfo = e.detail.userInfo;
      // 开始登录流程
      this.wxLogin();
    } else {
      // 用户点击了“拒绝”
      console.log('用户拒绝了授权');
    }
  },

  wxLogin: function() {
    // 2. 调用 wx.login 获取 code
    wx.login({
      success: (res) => {
        if (res.code) {
          const code = res.code;
          // 3. 将 code 发送到开发者服务器
          wx.request({
            url: 'https://your-backend.com/api/wx-login',
            method: 'POST',
            data: { code },
            success: (res) => {
              if (res.data.success) {
                // 登录成功,服务器返回了自定义登录态(如 token)
                const token = res.data.token;
                // 存储 token 到本地(如 Storage 或 globalData)
                wx.setStorageSync('auth_token', token);
                // 跳转到首页或进行其他操作
                wx.reLaunch({ url: '/pages/index/index' });
              }
            }
          });
        } else {
          console.log('登录失败!' + res.errMsg);
        }
      }
    });
  }
});

1.2 后端流程(Node.js 示例)

后端负责用 code 换取 openid 和 session_key,并建立自己的会话。

// server/controllers/authController.js
const axios = require('axios');

exports.wxLogin = async (req, res) => {
  const { code } = req.body;
  const appid = 'your-appid';
  const secret = 'your-app-secret';

  try {
    // 1. 使用 code 换取 session_key 和 openid
    const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${code}&grant_type=authorization_code`;
    const response = await axios.get(url);
    const { openid, session_key, unionid } = response.data;

    if (!openid) {
      return res.status(400).json({ success: false, msg: '无效的code' });
    }

    // 2. (可选) 验证用户信息完整性(如果前端传了 encryptedData 和 iv)
    // const { encryptedData, iv } = req.body;
    // const decodedUserInfo = decryptData(encryptedData, iv, session_key);

    // 3. 根据 openid 查找或创建本地用户
    let user = await UserModel.findOne({ openid });
    if (!user) {
      user = await UserModel.create({ openid, unionid });
    }

    // 4. 生成自定义登录态(如 JWT Token)
    const token = generateJWTToken({ userId: user._id, openid });

    // 5. 返回 token 给前端(注意不要返回 session_key)
    res.json({ success: true, token });
  } catch (error) {
    console.error('登录失败:', error);
    res.status(500).json({ success: false, msg: '服务器内部错误' });
  }
};

// 数据解密函数(示例)
function decryptData(encryptedData, iv, sessionKey) {
  // 使用 crypto 模块进行解密,具体实现略
  // 返回解密后的用户信息对象
}

2. 常见陷阱

  1. 混淆 wx.login 与 wx.getUserInfo

    • wx.login 用于获取临时凭证 code,是登录必需的。
    • wx.getUserInfo(现通常由按钮触发)用于获取用户头像、昵称等身份信息,是可选的。两者目的不同,不应混用。
  2. 在前端暴露敏感信息

    • AppSecret 必须保存在后端服务器,绝对不能在客户端代码或请求中暴露。
    • session_key 是服务器端的会话密钥,用于解密数据,绝不能通过网络传输给前端
  3. 未处理用户拒绝授权的情况

    • 用户可能拒绝授权 getUserInfo。前端必须有友好的引导和降级处理(例如,使用默认头像和昵称,允许后续再授权)。
  4. code 的一次性使用

    • 一个 code 只能使用一次,且有效期很短(约5分钟)。重复使用或过期使用会导致兑换失败。
  5. 会话管理不当

    • 仅依赖微信的 openid 作为身份标识不够安全。应使用自研的会话机制(如JWT、Session ID),并设置合理的过期时间。
    • 忘记将 session_key 与用户关联存储,导致后续解密手机号等操作失败。
  6. 未校验数据完整性(如果使用加密数据)

    • 当使用 <button open-type="getPhoneNumber"> 获取加密数据时,必须用 session_key 和 iv 在后端解密,并验证数据的完整性,防止伪造。
  7. 忽略网络请求的失败处理

    • wx.loginwx.request 都可能失败。代码中必须有完整的 fail 或 catch 回调,给出用户提示。

3. 总结

实现微信小程序授权登录,关键在于理解其前后端分离的流程:

  • 前端:引导授权 -> 获取 code -> 发送 code 至后端 -> 存储后端返回的自定义登录态。
  • 后端:用 code + AppSecret 换取 openid 和 session_key -> 创建/查找用户 -> 生成并返回自定义登录态。

牢记以下安全与体验要点:

  1. 安全第一AppSecret 和 session_key 永不泄露给客户端。
  2. 体验友好:妥善处理用户拒绝授权和网络异常。
  3. 设计健壮:建立自己的用户体系和会话管理,不依赖微信的临时凭证。

遵循官方文档的最新指引,并充分考虑上述陷阱,即可构建出一个安全、稳定且用户体验良好的小程序登录系统。


如果你在小程序开发、授权登录、前端Bug修复、Node.js接口开发中遇到问题,我可提供专业技术支持,全程闲鱼担保交易,快速解决问题!