zoukankan      html  css  js  c++  java
  • 小程序如何安全的登录

    近期刚好开发到有关小程序登录相关的逻辑,正好和大家好好聊一聊小程序登录逻辑。小程序登录的目的是为了更安全的账号体系,由于和微信支付绑定的很紧密。所以这里的登录更要要求严谨。之前看到过临时tid(有效期),或保存openid等方式,感觉多存在被人抓包复制,攻击的可能性。我通过仔细阅读官方文档,整理了一个,仅依靠一次性生成code的方式登录,可以保证登录用的“凭据”仅可使用一次,避免盗刷。

    登录是什么?

    抛开网上很多官方的解释,我认为就是让用户的客户端,可以在服务端指定一个固定的数据库Key。即用户携带登录“凭据”,服务端通过这个“凭据”转化成后台数据库中唯一的key(找到这个用户的所有信息),并可以凭借这个Key完成对用户信息的操作。而具体用什么方式,其实万变不离其宗。即如下图:

                          

    携带登录凭证是什么?有什么要求?

    每次登录携带的一个密钥(一下称为code),这个密钥就是打开用户数据库的钥匙,是用户身份的必要条件。那么我们对这个key有什么要求呢?

    • 可用于后端校验:说白了就是后端的用户ID不能明文存在前端(小程序或请求参数中),我们提供的code,不是用户ID,但是它必须可以(在服务端)转化成用户ID。
    • 可变性:如果code长期不变,那别人就相当于掌握了code到用户ID的映射关系,如果code长期不变,其实和直接传用户ID没什么区别,也就是没有安全性可言。顺带提一下有一些app采用的是一段有效期内不变的“有效期code”,不是说不好,对于不涉及现金支付的业务,也算是够用。如果涉及比较严谨的支付逻辑,最好还是采用“一次性密钥code”,这样别人就很难抓包盗用你的账户。
    • 随机性:即使是可变code,也不能有规律可循,也就是说生成code的方法要够随机

    搞一个“登录凭证”吧

    这样来看,我们的第一个目标是搞到这个code,其实小程序官方提供了这样一个API: 

    wx.login(Object object)
    调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。更多使用方法详见 小程序登录。

    注意:这个API并不是调用后就直接登录的,通过前面的我的解释,大家可以理解,这个其实就是那个生成“用户登录凭证”code,这个“登录凭证有效期5分钟”而且只能用一次。我们需要在http请求中携带这个code,以方便服务端登录验证并获取用户信息。更重要的是你需要每次发起http请求都重新生成一个(可以很好的防止“重放攻击”),因此我建议把获取code的代码放在http请求的组件里,对需要登录态的请求添加code参数。

                              

    这样前端部分就算是准备好了,下面我们来看服务端需要做什么。

    服务端怎么使用(验证)code?

    code通过参数的形式到达服务端后,我们的验证方式也是由微信官方提供,即调用微信的“auth.code2Session”接口,接口文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html

                 

    其中,appid是注册小程序的时候获取的,secret也是注册小程序的时候获取的,不要轻易改,查看后赶紧记好,js_code就是上面我们说的“登录凭证code”,grant_type就填“authorization_code”。然后在server端把这个请求发出去

    var code = req.query.code || req.body.code || req.headers.code;
      var url = `https://api.weixin.qq.com/sns/jscode2session?appid=${
        wechatConfig.appId
      }&secret=${
        wechatConfig.secret
      }&js_code=${code}&grant_type=authorization_code`;
      
      request.get(url, function(error, response, body) {
        if (!error) {
          if (body && body.length > 0) {
            var parseObject = JSON.parse(body);
            if (!req.session) {
              req.session = {};
            }
            // openid :  parseObject.openid;
            // unionId:  parseObject.unionid;
            // todo: About openid & unionid
            next();
          }
        } else {
          console.log('err:', error);
          next();
        }

     服务端甚至可以用这个unionId和openid直接(或稍加改造)入库做用户信息的key。剩下就是各自业务逻辑的事了。

    openId和unionId都是什么?

    微信服务器返回两个用户唯一ID,这两个id都可以标识唯一用户,也都可以作为我们业务的账号体系,有效期为永远不变(迁移接口的情况不算),但是他们俩是有区别的

    • openId是用户在当前应用下的唯一id,即openid可以锁定“用户 + 应用”。应用的意思就是指某个公共号、某个小程序等,因此同一用户在不同的公共号、订阅号、小程序、小游戏都算是不同应用,它们各自的openId也不同。
    • unionId是用户在腾讯微信体系下的唯一id,即同一用户在不同的公共号、订阅号、小程序、小游戏下,unionId是相同的。

    因此来说如果你想打通公共号(多数APP走公共号登录)和小程序登录的账号体系,共享用户数据,就要用unionId了,注意unionId是微信专属的,QQ并不走这套逻辑,QQ走自己的登录体系,虽然不同,但原理类似,只是微信更复杂(上面说的同一用户多应用的情况)。

    openId也是很有用的,很多支付相关的或微信官方接口都是用openId做参数的,因此我们还需要经常在两个间转换,有兴趣的朋友可以去官网看看其他玩法(佩服微信强大的账号体系啊)。

    获取用户信息的授权是什么?

    如果我们只想页面上展示头像、昵称的话,而不打算入库,或操作用户的数据。完全可以在小程序上直接获取。

    小程序的button组件: https://developers.weixin.qq.com/miniprogram/dev/component/button.html

    // open-type 的合法值
    // getUserInfo	获取用户信息,可以从bindgetuserinfo回调中获取到用户信息
    <button open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="onGotUserInfo">获取用户信息</button>
    
    onGotUserInfo: function(e) {
        console.log(e.detail.errMsg)
        console.log(e.detail.userInfo)
        console.log(e.detail.rawData)
    }
    // 其中e.detail.userInfo中包含用户的头像昵称

     缺点是必须由用户手动触发,并有个系统提示。一旦允许,下一次有效期内就不会再弹了。

    云开发的方案也不错

    小程序的云开发中集成了获取登录信息的方案,直接就能在云函数里面获取用户openid等信息

    附上文档地址: https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html

    基本方法如下:

    // 云函数入口文件
    const cloud = require('wx-server-sdk')
    cloud.init()
    //获取用户的openid
    exports.main = async(event, context) => {
     return event.userInfo; //返回用户信息
    }

    最后附上官方的架构图:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html   

                      

    以上就是我整理的小程序登录,因为涉及支付,所以需要研究一下细节,以及如何使用,确定安全才放心,希望对大家有用。

  • 相关阅读:
    Eclipse的tomcat插件
    sql优化:
    ecipse theme
    load()和get()的区别
    eclipse手动指定启动的jdk版本
    TOD&FIXME&XXX
    命令式和声明式
    显示器调色温
    jdeveloper优化:
    win7 登录后只能使用“临时配置文件”,原来的配置文件无法启用!
  • 原文地址:https://www.cnblogs.com/webARM/p/12443562.html
Copyright © 2011-2022 走看看