关于微信小程序用户登陆状态维护的两个方案

by pxz


发布于: 2018-05-08 所属分类: php 标签: 小程序 登陆状态  1547


<p>在我们web开发中, 通常用session保持用户登陆状态, 但是, 在小程序中, 是无法使用session的, 所以,我们必须制定一种登陆状态维护的方案.</p> <h2 id="h2--strong-1-strong-"><a name="<strong>方案1</strong>" class="reference-link"></a><span class="header-link octicon octicon-link"></span><strong>方案1</strong></h2><p>在微信小程序的文档中的方案是这样的, 如下图所示:</p> <p><img src="http://www.sgzhang.com/upload/2018/05/201805082154248059411.png" alt=""></p> <p>这种方案,服务器生成的登陆态(token)存入本地存储后, 之后的每次api请求都把这个token带上, 服务端验证token后返回业务数据, 这种方案可以满足大部分的需求, 但是,由于token是存储在客户端的,假设客户端存储的token可以被人窃取到, 别人拿到这个token就可以随意调用api操作用户的任何数据, 安全性无法保证.</p> <p>为了解决这个token的安全问题, 我们必须对这个token设定一个有效时间, 10分钟或者半个小时, 这样, 如果token被窃取后, 就只能在10分钟内或半个小时内有效, 安全性是提高了, 但是产生了一个问题,在小程序客户端在正常使用过程中,接口会频繁地返回token过期错误,需要重新调用登陆接口,在性能以及用户体验上都不友好, 有没有更好的解决方案呢?</p> <h2 id="h2--strong-2-strong-"><a name="<strong>方案2</strong>" class="reference-link"></a><span class="header-link octicon octicon-link"></span><strong>方案2</strong></h2><p>这是我们真实线上应用的一个方案, 方案的登陆时序图如下所示:</p> <div class="sequence-diagram">小程序->小程序:wx.login()获取code 小程序->开发者服务器:wx.request()发送code 开发者服务器->微信接口服务:登陆凭证校验接口\n(appid+appsecret+code) 微信接口服务->开发者服务器:返回session_key,openid 开发者服务器->开发者服务器:把openid关联的数据id\n用对称加密算法加密成token 开发者服务器->小程序:返回token 小程序->小程序:token存入storage 小程序->开发者服务器:\nwx.request()对token+当前时间戳\n进行authcoce加密发起业务请求 开发者服务器->开发者服务器:验证token是否使用过\n(token在redis中存在为使用过) 开发者服务器->开发者服务器:进行第一次解密\n验证时间戳\n(超过10分钟为过期token) 开发者服务器->开发者服务器:进行第二次解密\n(解密后获得openid关联的id) 开发者服务器->开发者服务器:记录token到redis\n有效期为10分钟 开发者服务器->开发者服务器:使用openid关联的id查询出openid 开发者服务器->小程序:返回业务数据</div><p>该方案在方案1的基础上,做了如下改动: </p> <pre><code>1. 服务器生成的登陆态(token)不设置有效期, 在服务端不改变加密密钥的情况下,token永不失效 2. 在小程序客户端,每次发起业务请求时, 不是直接附带本地存储的token, 而是先通过authcode对称加密算法, 把本地存储的token加上当前时间戳进行加密后作为请求的token参数值,附在请求参数上发起请求 3. 在服务端对token的验证时, 首先判断该token是否在redis里面, 如果有, 则表示, 10分钟内, 这个token值被成功请求过一次, 不能再次请求, 直接返回token验证失败的错误, 第二步, 对传过来的token进行authcode解密, 提取出时间戳,判断该时间戳是否超过10分钟, 如果超过10分钟, 返回token过期错误, 第三步, 对解密后的token除去时间戳后进行二次解密, 解密成功即可查询到用户的openid, 并且在redis或memcached里面记录该token, 有效期设为10分钟, 最后返回业务数据 </code></pre><p>这个方案的优势在于</p> <pre><code>1. 客户端传输过来的token, 只有10分钟的时效, 并且, 这个token, 只能使用一次, 就算被人窃取了, 也没什么影响. 2. 解决了方案1的频繁登陆问题, 同时在安全性方面也有了极大地提升. </code></pre><p>所以, 最终小程序的方案定下了使用该方案.</p> <p>最后, 如果你们有更好的方案, 欢迎留言讨论.</p>

发表评论

暂无评论

搜索
用户登陆