手机版

手把手教你的小程序登录认证

时间:2021-12-09 来源:互联网 编辑:宝哥软件园 浏览:

导语

为了方便小程序应用使用微信登录状态授权登录,微信小程序提供了一个开放的登录授权界面。乍一看觉得文档说的很有道理,但是实现起来真的很混乱,不知道如何管理和维护登录状态。本文将手把手教你如何在业务中访问和维护微信登录状态。

接入流程

这里公文上的流程图已经足够清晰,我们就直接细说补充。

手把手教会你小程序登录鉴权(图1)

首先,当你看这张图的时候,你肯定会注意到,相互交流的不仅仅是小程序的前端和我们自己的服务器,还有微信的第三方服务器。微信服务器在其中扮演什么角色?让我们一起来看一下登录验证过程,我们会明白的。

1.调用wx.login生成代码

wx.login () API的功能是为当前用户生成临时登录证书。这个临时登录证书的有效期只有五分钟。获得这个登录证书后,我们可以进行下一步:获取openid和session_key。

wx . log in({ success : function(loginRes){ if(loginRes . code){//example : 081 xytj1x q1y 40 SG 3 uj1 fwntj1l xyth } });2.获取openid和会话密钥

先介绍一下openid。已经在微信官方账号使用过的童鞋,应该对这个logo比较熟悉。在公共平台中,用于识别三个不同应用中每个用户的唯一标识,即每个应用中每个用户的openid不一致,因此我们可以在小程序中使用openid来识别用户的唯一性。

那么session_key是用来做什么的呢?有了用户ID,我们需要让用户登录,然后session_key保证当前用户会话操作的有效性。这个session_key是微信服务器分发给我们的。也就是说,我们可以用这个logo来间接维护我们小程序用户的登录状态,那么这个session_key是怎么来的呢?我们需要在自己的服务器上申请微信提供的第三方界面https://api.weixin.qq.com/sns/jscode2session。该界面需要带来四个参数字段:

手把手教会你小程序登录鉴权(图2)

从这些参数中,我们可以看到,要请求这个接口,我们必须首先调用wx.login()来获取用户当前会话的代码。那么我们为什么要在服务器端请求这个接口呢?其实为了安全起见,如果我们在前端通过请求调用这个接口,难免会把我们小程序的appid和我们小程序的秘密暴露给外界,同时也会把微信服务器发出的session_key暴露给“有心人”,给我们的业务安全带来很大的风险。除了在服务器上获取session_key,我们还需要注意两点:

Session_key和微信分发的代码一一对应,同一个代码只能交换一次session_key。每次调用wx.login()时,都会发出一个新的代码和相应的session_key。为了保证用户体验和登录状态的有效性,开发人员需要清楚地知道,当用户需要再次登录时,会调用wx.login()。

Session_key无效,即使不调用wx.login,session_key也会过期,过期时间与用户使用小程序的频率成正相关,但是具体的时间长度开发者和用户都无法获得。

函数getSessionKey(代码,appid,appSecret){ var opt={ method : ' GET ',URL : ' https://API . weixin . QQ . com/SNS/jscode 2 session ',params: { appid:secret: appSecret,js_code: code,grant _ type : ' authorization _ code ' };

return http(opt).then(function (response) { var data = response.data; if (!data.openid || !data.session_key || data.errcode) { return { result: -2, errmsg: data.errmsg || '返回数据字段不完整' } } else { return data } });}

3. 生成3rd_session

前面说过通过session_key来“间接”地维护登录态,所谓间接,也就是我们需要自己维护用户的登录态信息,这里也是考虑到安全性因素,如果直接使用微信服务端派发的session_key来作为业务方的登录态使用,会被“有心之人”用来获取用户的敏感信息,比如wx.getUserInfo()这个接口呢,就需要session_key来配合解密微信用户的敏感信息。

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

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

const crypto = require('crypto');return getSessionKey(code, appid, secret)    .then(resData => {        // 选择加密算法生成自己的登录态标识        const { session_key } = resData;        const skey = encryptSha1(session_key);    });    function encryptSha1(data) {    return crypto.createHash('sha1').update(data, 'utf8').digest('hex')}

4. checkSession

前面我们将skey存入前端的storage里,每次进行用户数据请求时会带上skey,那么如果此时session_key过期呢?所以我们需要调用到wx.checkSession()这个API来校验当前session_key是否已经过期,这个API并不需要传入任何有关session_key的信息参数,而是微信小程序自己去调自己的服务来查询用户最近一次生成的session_key是否过期。如果当前session_key过期,就让用户来重新登录,更新session_key,并将最新的skey存入用户数据表中。

checkSession这个步骤呢,我们一般是放在小程序启动时就校验登录态的逻辑处,这里贴个校验登录态的流程图:

手把手教会你小程序登录鉴权(图3)

下面代码即校验登录态的简单流程:

let loginFlag = wx.getStorageSync('skey');if (loginFlag) {    // 检查 session_key 是否过期    wx.checkSession({        // session_key 有效(未过期)        success: function() {            // 业务逻辑处理        },            // session_key 过期        fail: function() {            // session_key过期,重新登录            doLogin();        }    });) else {    // 无skey,作为首次登录    doLogin();}

5. 支持emoji表情存储

如果需要将用户微信名存入数据表中,那么就确认数据表及数据列的编码格式。因为用户微信名可能会包含emoji图标,而常用的UTF8编码只支持1-3个字节,emoji图标刚好是4个字节的编码进行存储。

这里有两种方式(以mysql为例):

1.设置存储字符集

在mysql5.5.3版本后,支持将数据库及数据表和数据列的字符集设置为utf8mb4,因此可在/etc/my.cnf设置默认字符集编码及服务端编码格式

// my.cnf[client]default-character-set=utf8mb4[mysql]default-character-set=utf8mb4[mysqld]character-set-client-handshake = FALSEcharacter-set-server=utf8mb4collation-server=utf8mb4_unicode_ci

设置完默认字符集编码及服务端字符集编码,如果是对已经存在的表和字段进行编码转换,需要执行下面几个步骤:

  • 设置数据库字符集为utf8mb4
ALTER DATABASE 数据库名称 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
  • 设置数据表字符集为utf8mb4
ALTER TABLE 数据表名称 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • 设置数据列字段字符集为utf8mb4
ALTER TABLE 数据表名称 CHANGE 字段列名称 VARCHAR(n) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

这里的COLLATE指的是排序字符集,也就是用来对存储的字符进行排序和比较的,utf8mb4常用的collation有两种:utf8mb4_unicode_ci和utf8mb4_general_ci,一般建议使用utf8mb4_unicode_ci,因为它是基于标准的Unicode Collation Algorithm(UCA)来排序的,可以在各种语言进行精确排序。这两种排序方式的具体区别可以参考:What's the difference between utf8_general_ci and utf8_unicode_ci

  1. 通过使用sequelize对emoji字符进行编码入库,使用时再进行解码

这里是sequelize的配置,可参考Sequelize文档

{       dialect: 'mysql',    // 数据库类型       dialectOptions: {             charset: 'utf8mb4',         collate: "utf8mb4_unicode_ci"      },}

最后

前面讲了微信小程序如何接入微信登录态标识的详细流程,那么如何获取小程序中的用户数据以及对用户敏感数据进行解密,并保证用户数据的完整性,我将在下一篇文章给大家做一个详细地介绍。

团队开源

腾讯IVWEB团队的工程化解决方案feflow已经开源:Github主页:feflow

如果对您的团队或者项目有帮助,请给个Star支持一下哈~

版权声明:手把手教你的小程序登录认证是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。