微信小程序登录态控制深入分析


Posted in Javascript onApril 12, 2017

微信小程序登录态控制深入分析

最近微信小程序终于开放了个人注册,我当然不能浪费这个炫技的好机会,“菲麦日程”小程序正在全力推进中,尽请期待~~
在登录态控制中,摸索尝试了小一阵子,特此分享

一、微信建议的登录态控制

微信小程序登录态控制深入分析

说明:

1)小程序内通过wx.login接口获得code
2)将code传入后台,后台对微信服务器发起一个https请求换取openid、session_key
3)后台生成一个自身的3rd_session(以此为key值保持openid和session_key),返回给前端。

PS:微信方的openid和session_key并没有发回给前端小程序

4)小程序拿到3rd_session之后保持在本地
5)小程序请求登录区内接口,通过wx.checkSession检查登录态,如果失效重新走上述登录流程,否则待上3rd_session到后台进行登录验证

二、可不可以不接受它的建议

不是我反骨,而是我的微信小程序不需要获取什么私密数据,用不到session_key,只需要一个openid,微信特别强调了,为了自身应用安全,session_key 不应该在网络上传输,可没说不可以传输openid,那么如果我将openid直接返回给前端小程序,会不会方便很多?下面我们来具体分析下:

永不过期的openid:

要知道,session_key有过期时间,必须适时重新获取,而针对每一个小程序,唯一标识用户的openid可不会过期,如果只在用户第一次登录的时候,通过后台请求到openid,小程序缓存到本地,之后每次请求都以这个openid作为唯一凭证,岂不是一本万利~~

事实上,上面的做法忽略了一个致命的问题,手机上是可以切换微信账户的,如果手机I上原先登录了账户A,已经保存了用户A的openid,有一天手机I上切换到了账户B上,小程序检测到openid存在,并不会重新获取openid,那么账户B就请求到了账户A的数据,这就造成数据乱象了

登录态过期后重新获取openid:

上述的问题并不能打消我使用openid作为登录凭证的念头,只需要稍作改进,数据就不会乱窜:每次进入小程序通过wx.checkSession检测登录是否失效,如果失效重新获取openid,要知道,手机切换了登录账号,登录态一定会过期,这样虽不能一本万利,但也足够省心。

这个时候应该有一个然而,以永不过期的openid作为登录凭证,并不是明智之举,一旦被人截获,就再也没有翻身的机会了,而维护一个第三发的session,至少拥有有效期,这在很大程度上增加了安全性。并且,现在不需要使用session_key,不代表以后,保持系统的可扩展性,才能以不变应万变

事实证明,我还是应该接受它的建议

三、基于redis维护3rd_session

维护3rd_session需要一个内存数据库,这里我选用了redis

维护会话态是内存数据库的典型应用场景,毕竟量小,并且要求速度快,这么一个小应用,当然也可以自己在内存中维护一个对象来进行会话id的处理,但是肯定难以跟一个成熟的系统相媲美

抛开代码实现,这似乎就是一句话可以概括的事情,生成一个唯一的随机串sessionid,以此为key,openid和微信方的session_key为value存入redis,并把sessionid传回给客户端。

但是,翻遍小程序的官方文档,除了一句据说的wx.checkSession对开发者来说是透明的,并没有小程序登录态何时过期的具体说明,如何才能同步前后端的会话过期时间呢?

四、前后端会话过期时间同步

一开始,我还是试图寻找小程序的登录态时效

{"session_key":"...","expires_in":7200,"openid":"..."}

在code2session接口返回的数据中,有一个可疑的字段expires_in,它的值是7200,似乎存储到redis中的sessionid设置为7200就可以同步了。可是实践的结果再次让人失望,不管是设置成7200还是60*60*24(一天),都出现了小程序会话尚在有效期,而服务器端会话已经过期的情况,这直接导致了小程序带着已经缓存的sessionid到服务器端请求接口,返回未登录的情况

看来还是只有wx.checkSession才知道小程序会话啥时候过期,于是,作战方案重新做了调整,如果wx.checkSession检测到会话失效,那么带上已经缓存在本地的sessionid(如果有的话),重新发起登录请求,后台从code2session中拿到新的请求结果后,生成新的随机sessionid并入库reids,并且把老的sessionid移除(如果有的话)

当然不移除也不会带来什么功能上的影响,但是会存在两个问题,首先,跟使用open_id作为登录凭证一样,旧的sessionid永不过期,其次,无用的session数据占用redis资源,会拖垮访问性能

五、“脱贫致富指数”统计

我给小程序的用户数安了一个高大上的名字“脱贫致富指数”,纯属娱乐,切勿当真

为了统计使用小程序的用户数,需要一个表来保存用户数据,后台提供一个接口,让小程序将用户数据传上来进行一个注册操作,当然可以把这个功能合并到登录接口上,每次登录都把前端小程序获得的微信用户数据带上,如果发现数据库中还没有该用户的信息,则进行入库操作

不难发现,其实只需要用户第一次登录的时候注册一次就行了,所以上述方法虽然简便,但是有点浪费带宽,所以应该额外提供一个注册接口,登录接口只需要返回一个用户是否已经注册的标志,让客户端决定是否需要获取用户信息,进行注册操作(当然后台也不会让同一个用户重复入库)

那么问题就变成如何判断用户是第一次登录了:

1)判断登录请求中有没有带上sessionid,如果没带上,肯定是第一次登录;如果带上了就是登录过的用户?不,别忘了,前面说过,用户可能会在同一设备切换账户,那就有可能在登录接口中带上了别人sessionid,那并不能表明用户曾经登录过

2)通过带上来的sessionid从redis中拿到openid,跟在code2session新请求到的openid进行比对,如果一致,可以证明用户曾经登录过,否则,仍需要用户进行注册

总结

时间是浪费了那么一些,但是进过思考摸索,代码肯定更完备了~~

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
web的各种前端打印方法之jquery打印插件PrintArea实现网页打印
Jan 09 Javascript
Dojo Javascript 编程规范 规范自己的JavaScript书写
Oct 26 Javascript
JS实现iframe自适应高度的方法(兼容IE与FireFox)
Jun 24 Javascript
jQuery事件绑定用法详解
Sep 08 Javascript
jQuery插件FusionWidgets实现的Bulb图效果示例【附demo源码下载】
Mar 23 jQuery
ztree简介_动力节点Java学院整理
Jul 19 Javascript
JavaScript闭包原理与用法实例分析
Aug 10 Javascript
使用原生js编写一个简单的框选功能方法
May 13 Javascript
使用 Element UI Table 的 slot-scope方法
Oct 10 Javascript
React实现类似淘宝tab居中切换效果的示例代码
Jun 02 Javascript
在vue中实现echarts随窗体变化
Jul 27 Javascript
JavaScript实现轮播图效果
Oct 30 Javascript
JavaScript数据结构之二叉查找树的定义与表示方法
Apr 12 #Javascript
微信小程序微信支付接入开发实例详解
Apr 12 #Javascript
JavaScript数据结构之广义表的定义与表示方法详解
Apr 12 #Javascript
JavaScript数据结构之数组的表示方法示例
Apr 12 #Javascript
easyui-edatagrid.js实现回车键结束编辑功能的实例
Apr 12 #Javascript
Vue生命周期示例详解
Apr 12 #Javascript
easyui关于validatebox实现多重规则验证的方法(必看)
Apr 12 #Javascript
You might like
Excel数据导入Mysql数据库的实现代码
2008/06/05 PHP
php对mongodb的扩展(初出茅庐)
2012/11/11 PHP
php rmdir使用递归函数删除非空目录实例详解
2016/10/20 PHP
js 获取子节点函数 (兼容FF与IE)
2010/04/18 Javascript
基于JQuery的访问WebService的代码(可访问Java[Xfire])
2010/11/19 Javascript
两个Javascript小tip资料
2010/11/23 Javascript
js+html+css实现鼠标移动div实例
2013/01/30 Javascript
终于解决了IE8不支持数组的indexOf方法
2013/04/03 Javascript
jquery内置验证(validate)使用方法示例(表单验证)
2013/12/04 Javascript
JS使用getComputedStyle()方法获取CSS属性值
2014/04/23 Javascript
jquery实现勾选复选框触发事件给input赋值
2015/02/01 Javascript
谈谈基于iframe、FormData、FileReader三种无刷新上传文件的方法
2015/12/03 Javascript
JavaScript 闭包机制详解及实例代码
2016/10/10 Javascript
Jquery 整理元素选取、常用方法一览表
2016/11/26 Javascript
JavaScript触发onScroll事件的函数节流详解
2016/12/14 Javascript
在 Node.js 中使用 async 函数的方法
2017/11/17 Javascript
vue组件中的数据传递方法
2018/05/14 Javascript
微信小程序实现折叠展开效果
2018/07/19 Javascript
详解element-ui中form验证杂记
2019/03/04 Javascript
在React中写一个Animation组件为组件进入和离开加上动画/过度效果
2019/06/24 Javascript
实现vuex与组件data之间的数据同步更新方式
2019/11/12 Javascript
Node.js API详解之 dns模块用法实例分析
2020/05/15 Javascript
JavaScript如何实现监听键盘输入和鼠标监点击
2020/07/20 Javascript
Python判断变量是否已经定义的方法
2014/08/18 Python
零基础写python爬虫之使用Scrapy框架编写爬虫
2014/11/07 Python
python实现用户登陆邮件通知的方法
2015/07/09 Python
python Django批量导入数据
2016/03/25 Python
python实现转圈打印矩阵
2019/03/02 Python
由Python编写的MySQL管理工具代码实例
2019/04/09 Python
对Django中static(静态)文件详解以及{% static %}标签的使用方法
2019/07/28 Python
Python加速程序运行的方法
2020/07/29 Python
审核会计岗位职责
2013/11/08 职场文书
公司会计岗位职责
2014/02/13 职场文书
创先争优承诺书范文
2014/03/31 职场文书
一道JS算法面试题——冒泡、选择排序
2021/04/21 Javascript
Selenium浏览器自动化如何上传文件
2022/04/06 Python