小程序简单开发:关于登录的一些事

2020-04-1911:44:16APP与小程序开发Comments1,826 views字数 4382阅读模式

梳理登录流程

这里有几个点是要注意的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

  1. 要注意 es6语法使用,es6的语法会在小程序里面更加的有用,其中最关键的地方就是小程序的 api 大部分都是异步的,旧有的方式要异步就必须要要回调,而回调的就会导致代码逻辑容易发生混乱,所以需要使用promise并且进行接口的封装。
  2. 要注意效率,例如对于 code 的获取,首次和非首次要注意首次获取后保存下来,然后非首次获取就可以从缓存里面直接获取,类似这种有好几个地方,所以需要注意好。
  3. 要注意先理清楚业务逻辑和登录逻辑和产品体验逻辑,一定要先画好流程图,因为小程序的逻辑相较一般的逻辑要稍微“绕”,对,是很绕的绕,所以需要注意理顺流畅。
  4. 要注意接口的调用先后顺序,跟流程图的关系很大,对比官方文档,一步步处理,又因为使用异步,所以需要弄清楚 promise 异步的 resolve 和 reject,在多重promise 里面会比较麻烦,不过也是有技巧可以回避的,详情下面会说。
  5. 需要注意签名解密处理,虽然这是服务器端做的,但是也需要了解好是怎么一个操作,因为也需要解析给服务器端的同事,如何配合小程序来做处理。
  6. 需要理解各个关键的变量元素的意思,code,session_key,3rd_session,openid,unioinid的意义,这样才能协助理解文档的整体思路。
  7. 需要注意 openId 和 unioinId的使用

微信小程序登录流程图

引用Yinjie 的图,因为这个图比官方的要看得明白一点。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

小程序简单开发:关于登录的一些事文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

代码逻辑流程图

引用Yinjie 的图,因为这个图比官方的要看得明白一点。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

小程序简单开发:关于登录的一些事文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

腾讯 weapp-session的代码流程图

引用腾讯 weapp-session 的图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

小程序简单开发:关于登录的一些事文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

他们还出了一个比较详细的,一步步的代码处理流程,可以对比自己的程序进行检查。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

  1. 客户端(微信小程序)发起请求 request
  2. weapp-session-client 包装 request
    • 首次请求
      • 调用 () 和 () 接口获得 coderawData 和 signature
      • requset 的头部带上 coderawData 和 signature
      • 保存 code 供下次调用
    • 非首次请求
  3. 服务器收到请求 request,中间件从头部提取 coderawData 和 signature 字段
    • 如果 code 为空,跳到第 4 步
    • 如果 code 不为空,且 rawData 不为空,需要进行签名校验
      • 使用 codeappidapp_secret 请求微信接口获得 session_key 和 openid
        • 如果接口失败,响应 ERR_SESSION_KEY_EXCHANGE_FAILED
      • 使用签名算法通过 rawData 和 session_key 计算签名 signature2
      • 对比 signature 和 signature2
        • 签名一致,解析 rawData 为 wxUserInfo
          • 把 openid 写入到 wxUserInfo
          • 把 (code, wxUserInfo) 缓存到 Redis
          • 把 wxUserInfo 存放在 request.$wxUserInfo 里
          • 跳到第 4 步
        • 签名不一致,响应 ERR_UNTRUSTED_RAW_DATA
    • 如果 code 不为空,但 rawData 为空,从 Redis 根据 code 查询缓存的用户信息
      • 找到用户信息,存放在 request.$wxUserInfo 字段里,跳到第 4 步
      • 没找到用户信息(可能是过期),响应 ERR_SESSION_EXPIRED
  4. request 被业务处理,可以使用 request.$wxUserInfo 来获取用户信息(request.$wxUserInfo 可能为空,业务需要自行处理)

流程图总结

  1. code 是微信用户的登录凭证,打开小程序登录的时候获取的只属于微信这个用户的登录凭证,需要注意的是,这个登录凭证只供微信小程序使用的。
  2. session_key 是微信用户在小程序里面的登录态信息,相当于是微信给这个用户颁发的一个登录 session,官网地址
    • 他有一个过期时间{"session_key":"...","expires_in":7200,"openid":"..."},需要定期使用检测。
  3. openId ,用户的唯一标识
  4. unioinId,如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。
  5. 一般来说,openId 就是微信用户的唯一标识,但是因为微信产品很多,所以会出现多个微信产品使用不同的 openId 来标识用户,但是对于我们做业务接入的话,就买办法使用了,所以建议是统一使用 unioinid,因为一般来说,一般的业务都会有公众号,小程序联合使用的。
  6. 3rd_session 是一般是指我们自己公司的服务器的 session,一般来说,可以跟原来的业务的 session 一起使用,不过这个 session 的过期时间一定要比小程序的session_key 的过期时间要长,这样可以减少 session 的多次重复创建,另外一般我们自己公司的服务器的 session 管理都会使用类似 redis 之类的数据库进行管理的,这个大致了解一下,因为其他文章会提到。
  7. 为什么要用2个 sessionsession_key 和3rd_session),那是因为session_key是微信的登录态,3rd_session是我们业务系统的登录态,两边各有一个登录态,所以需要将2个登录态合并为一个 session,在这里面是合并为3rd_session,并保存到我们业务系统上,然后每次需要使用的时候,小程序带上这个3rd_session访问我们的业务系统,通过处理,可以返回我们需要 unioinid 和其他 session 信息而不用每次都去获取一个新的session_key(因为微信有限制code 的使用,要用 code 换 session_key),总的来说,就是使用3rd_session来管理小程序的登录态

关于解密

根据官方文档: ,数据校验是为了提高数据的安全性,我们需要获取用户的 unioinid,需要调用接口来获取,但是一般情况下,获取出来的数据是文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

{
  "nickName": "Band",
  "gender": 1,
  "language": "zh_CN",
  "city": "Guangzhou",
  "province": "Guangdong",
  "country": "CN",
  "avatarUrl": ""
}

对于需要业务接入的话,没有 unioinid 是没意义的,所以需要根据官方的方式来进行解密,解密后的数据里面有 unioinid 了文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

{
    "openId": "OPENID",
    "nickName": "NICKNAME",
    "gender": GENDER,
    "city": "CITY",
    "province": "PROVINCE",
    "country": "COUNTRY",
    "avatarUrl": "AVATARURL",
    "unionId": "UNIONID",
    "watermark":
    {
        "appid":"APPID",
    "timestamp":TIMESTAMP
    }
}

封装网络接口

因为小程序的所有网络请求都是异步的,那么异步就会出现很多重的回调的问题,所以改成了 promise,promise 的使用要谨慎注意 resolve 和 return的处理。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

例如这样:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

const httpRequest = (api, data) => {
    let serverHost = env.serverHost;

    return new Promise(function (resolve, reject) {
        //发起网络请求
        ({
            url: serverHost + api,
            data: data,
            header: {
                'content-type': 'application/x-www-form-urlencoded'
            },
            success: function (res) {
                if (.errno === 0) {
                    // 需要下一步处理的就用 resolve 返回
                    resolve();
                }
                else {
                    ("http fail:api:" + api + "res:" + (res));
                    // 需要跳出循环处理的就用 reject
                    reject();
                }
            }, fail: function (res) {
                ("http fail:api:" + api + "res:" + (res));
                // 需要跳出循环处理的就用 reject
                reject(res);
            }
        })
    })
};

在多重 promise 的情况下,则需要注意2个地方:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

  1. 需要返回一个可使用的 promise 实例
  2. 即使有异步并且出现分支的情况下,尽量集中在一个统一的流里面处理,用统一的 reject 跳出,而不是各个异步单独跳出,这样流程会更加统一和方便管理。
getCode() // 获取 wx code
            .then(code => {
                wxCode = code;
                // 这里getSetting是一个返回的 promise实例,如上面的那个
                return getSetting(); // 获取 setting
            })
            .then(res => {
                if ([""]) {
                    // 这里getUserInfo是一个返回的 promise实例
                    return getUserInfo(self);
                } else {
                    ("first auth none:" + (res));
                    // 类似
                    return util.showModal("亲,还没有授权!")
                        .then(res => {
                            return getAuth("userInfo");
                        }).then(res => {
                            // 检查授权是否正常
                            return getSetting();
                        })
                        .then(res => {
                            if ([""]) {
                                return getUserInfo(self);
                            } else {
                                return Promise.reject(res);
                            }
                        });
                }
            })
            .catch(err=>{
                ("err"+err);    
            })

注意友好的提示

微信小程序“授权失败”场景需要优雅处理,提升用户体验,参考这里:可以稍微看到是如何生效的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

通过在里面插入一个判断处理,判断没有权限即弹出 modal 提示框:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html

({
    success: function success(res) {
        ();
        var authSetting = ;
        if (authSetting[''] === false) {
                ({
                    title: '用户未授权',
                    content: '如需XXXXXXX。',
                    showCancel: false,
                    success: function (res) {
                        if () {
                            ('用户点击确定')
                            ({
                                success: function success(res) {
                                }
                            });
                        }
                    }
                })
        }
    }
});
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/18211.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/xcx/18211.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定