微信小程序登录授权流程

openid:用户的唯一标识
session_key:本次登录的会话密钥(保证当前用户进行会话操作的有效性)


1. 调用wx.login生成code

wx.login() 这个API的作用就是为当前用户生成一个临时的登录凭证,这个临时登录凭证的有效期只有五分钟。

wx.login({
    success: res => {
        if (res.code) {
            app.globalData.code = res.code; // 获得code 存入全局
        } else {
            console.log('获取用户登录态失败!' + res.errMsg);
            that.onLogin(); // 重新登录
        }
    },
});

2. 获取openid和session_key(后台服务器)

我们拿到code这个登录凭证后就可以 在服务器后台调用 auth.code2Session接口,完成登录流程。(使用 code 换取 openidsession_key 等信息。
【注意:必须要在本项目后台服务中才能成功,在小程序端是无效的】

这个接口需要带上四个请求参数

参数必填
appid小程序 appId
secret小程序 appSecret
js_code前面调用wx.login派发的code
grant_type授权类型,此处只需填写 ‘authorization_code’
  • session_key和微信派发的code是一一对应的,同一code只能换取一次session_key。每次调用wx.login(),都会下发一个新的code和对应的session_key,为了保证用户体验和登录态的有效性,开发者需要清楚用户需要重新登录时才去调用wx.login()
  • session_key是有时效性的,即便是不调用wx.login,session_key也会过期,过期时间跟用户使用小程序的频率成正相关,但具体的时间长短开发者和用户都是获取不到的
function getSessionKey(code, appid, appSecret) {
    wx.request({
        url: 'https://api.weixin.qq.com/sns/jscode2session',
        data: {
            appid: appid,
            secret: appSecret,
            js_code: code,
            grant_type: 'authorization_code',
        },
        method: 'GET',
        success: function (res) {
            var obj = {
                openid: res.data.openid, // 用户唯一标识
                session_key: res.data.session_key, // 会话密钥
                unionid: res.data.unionid, // 用户在开放平台的唯一标识符
            };
            wx.setStorageSync('user', obj);
        },
    });
}

3. 生成3rd_session

如果直接使用微信服务端派发的session_key来作为业务方的登录态使用,会被“有心之人”用来获取用户的敏感信息,比如wx.getUserInfo()这个接口呢,就需要session_key来配合解密微信用户的敏感信息。

那么我们如果生成自己的登录态标识呢,这里可以使用几种常见的不可逆的哈希算法,比如md5、sha1等,将生成后的登录态标识(这里我们统称为’skey’)返回给前端,并在前端维护这份登录态标识(一般是存入storage)。而在服务端呢,我们会把生成的skey存在用户对应的数据表中,前端通过传递skey来存取用户的信息。

可以看到这里我们使用了sha1算法来生成了一个skey:

const crypto = require('crypto');

function encryptSha1(data) {
    return crypto.createHash('sha1').update(data, 'utf8').digest('hex');
}

const skey = encryptSha1(session_key);
wx.setStorageSync(skey, skey);

4. 调用wx.checkSession()校验当前session_key是否已经过期

wx.checkSession() 这个API并不需要传入任何有关session_key的信息参数,而是微信小程序自己去调自己的服务来查询用户最近一次生成的session_key是否过期。如果当前session_key过期,就让用户来重新登录,更新session_key,并将最新的skey存入用户数据表中。

let loginFlag = wx.getStorageSync('skey');
if (loginFlag) {
    wx.checkSession({ // 检查 session_key 是否过期
        success: function () { //session_key 未过期,并且在本生命周期一直有效
            // 业务逻辑处理
        },
        // session_key 过期
        fail: function () { // session_key过期,重新登录
            that.onLogin();
        },
    });
} else {
    // 无skey,作为首次登录
    that.onLogin();
}

登录授权流程

function onLogin() {
    const that = this;
    wx.login({
        success: res => {
            if (res.code) {
                app.globalData.code = res.code; // 获得code 存入全局
                try {
                    canIUseFlag = wx.canIUse('getSetting');
                } catch (canIuseEX) {}
                if (canIUseFlag) {
                    wx.getSetting({
                        // 获取用户的当前设置 判断是否授权
                        success: res => {
                            // 表示scope.userInfo这个权限已经授权。
                            if (res.authSetting['scope.userInfo']) {
                                // 调用wx.getUserInfo 获取用户信息
                                that.getUserInfo();
                            } else {
                                // 表示scope.userInfo这个权限未授权。
                                // 向用户发起 scope.userInfo 授权请求
                                wx.authorize({
                                    scope: 'scope.userInfo',
                                    success(rs) {
                                        // 调用wx.getUserInfo 获取用户信息
                                        that.getUserInfo();
                                    },
                                    fail(rs) {
                                        console.log(rs);
                                    },
                                });
                                util.hideLoading();
                                return;
                            }
                        },
                        fail(rs) {
                            console.log('用户暂未授权');
                        },
                    });
                }
            } else {
                that.onLogin();
            }
        },
        fail(rs) {
            that.onLogin();
        },
    });
    util.hideLoading();
}

// 获取用户信息
function getUserInfo() {
    // 必须是在用户已经授权的情况下调用
    wx.getUserInfo({
        success: function (res) {
            let userInfo = res.userInfo;
            let wx_user_info = {
                nickName: userInfo.nickName,
                avatarUrl: userInfo.avatarUrl,
                gender: userInfo.gender, //性别 0:未知、1:男、2:女
                province: userInfo.province,
                city: userInfo.city,
                country: userInfo.country,
            };
            wx.setStorageSync('wx_user_info', wx_user_info);
        },
    });
}
posted @ 2022-07-20 18:15  猫老板的豆  阅读(2707)  评论(0编辑  收藏  举报