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


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 相关文章推荐
jquery 多级下拉菜单核心代码
May 21 Javascript
jQuery的写法不同导致的兼容性问题的解决方法
Jul 29 Javascript
jquery mobile changepage的三种传参方法介绍
Sep 13 Javascript
JS中数组Array的用法示例介绍
Feb 20 Javascript
谈谈JavaScript类型系统之Math
Jan 06 Javascript
jquery仿苹果的时间/日期选择效果
Mar 08 Javascript
js自定义弹框插件的封装
Aug 24 Javascript
在一个页面实现两个zTree联动的方法
Dec 20 Javascript
原生JS控制多个滚动条同步跟随滚动效果
Dec 22 Javascript
angularJs中$scope数据序列化的实例
Sep 30 Javascript
微信小程序(订阅消息)功能
Oct 25 Javascript
javascript实现时钟动画
Dec 03 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
php中将字符串转为HTML的实体引用的一个类
2013/02/03 PHP
php使用指定字符列表生成随机字符串的方法
2015/04/18 PHP
PHP实现对png图像进行缩放的方法(支持透明背景)
2015/07/15 PHP
php+redis消息队列实现抢购功能
2018/02/08 PHP
jquery实现文本框鼠标右击无效以及不能输入的代码
2010/11/05 Javascript
js实现图片漂浮效果的方法
2015/03/02 Javascript
js实现表单及时验证功能 用户信息立即验证
2016/09/13 Javascript
使用JSON格式提交数据到服务端的实例代码
2018/04/01 Javascript
weui上传多图片,压缩,base64编码的示例代码
2020/06/22 Javascript
Python实现简单的可逆加密程序实例
2015/03/05 Python
Python复制文件操作实例详解
2015/11/10 Python
Python使用BeautifulSoup库解析HTML基本使用教程
2016/03/31 Python
利用Python如何将数据写到CSV文件中
2018/06/05 Python
Python全排列操作实例分析
2018/07/24 Python
python之消除前缀重命名的方法
2018/10/21 Python
pycharm: 恢复(reset) 误删文件的方法
2018/10/22 Python
PyQt5 QTable插入图片并动态更新的实例
2019/06/18 Python
Python 获取 datax 执行结果保存到数据库的方法
2019/07/11 Python
Python过滤掉numpy.array中非nan数据实例
2020/06/08 Python
利用Python实现斐波那契数列的方法实例
2020/07/26 Python
Python爬虫+tkinter界面实现历史天气查询的思路详解
2021/02/22 Python
Django如何重置migration的几种情景
2021/02/24 Python
CSS实现圆形放大镜狙击镜效果 只有圆圈里的放大
2012/12/10 HTML / CSS
使用CSS3配合IE滤镜实现渐变和投影的效果
2015/09/06 HTML / CSS
boostrap modal 闪现问题的解决方法
2020/09/01 HTML / CSS
铭宣海淘转运:美国、日本、英国转运等全球转运公司
2019/09/10 全球购物
西安当代医院管理研究院笔试题
2015/12/11 面试题
《青蛙看海》教学反思
2014/04/23 职场文书
2014年教研活动总结范文
2014/04/26 职场文书
居委会个人对照检查材料思想汇报
2014/09/29 职场文书
预备党员自我评价范文
2015/03/04 职场文书
2015秋季运动会通讯稿
2015/07/18 职场文书
详解盒子端CSS动画性能提升
2021/05/24 HTML / CSS
一文彻底理解js原生语法prototype,__proto__和constructor
2021/10/24 Javascript
零基础学java之方法的定义与调用详解
2022/04/10 Java/Android
JS前端监控采集用户行为的N种姿势
2022/07/23 Javascript