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


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 相关文章推荐
JavaScript中this关键字使用方法详解
Mar 08 Javascript
如何使用jQuery来处理图片坏链具体实现步骤
May 02 Javascript
js实现省市联动效果的简单实例
Feb 10 Javascript
jquery选择器使用详解
Apr 08 Javascript
flash+jQuery实现可关闭及重复播放的压顶广告
Apr 15 Javascript
JavaScript的类型、值和变量小结
Jul 09 Javascript
AngularJS实现标签页的两种方式
Sep 05 Javascript
addEventListener()与removeEventListener()解析
Apr 20 Javascript
让微信小程序支持ES6中Promise特性的方法详解
Jun 13 Javascript
express框架实现基于Websocket建立的简易聊天室
Aug 10 Javascript
vue 自定义右键样式的实例代码
Nov 06 Javascript
JS数组降维的实现Array.prototype.concat.apply([], arr)
Apr 28 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
全国FM电台频率大全 - 19 广东省
2020/03/11 无线电
PHP 程序员也要学会使用“异常”
2009/06/16 PHP
php网站被挂木马后的修复方法总结
2014/11/06 PHP
php获取本周星期一具体日期的方法
2015/04/20 PHP
thinkphp自定义权限管理之名称判断方法
2017/04/01 PHP
Yii2实现ActiveForm ajax提交
2017/05/26 PHP
json 入门基础教程 推荐
2009/10/31 Javascript
JavaScript 字符串与数组转换函数[不用split与join]
2009/12/13 Javascript
使用javascript创建快捷方式的简单实例
2013/08/09 Javascript
jQuery 1.9使用$.support替代$.browser的使用方法
2014/05/27 Javascript
jquery动态改变div宽度和高度
2015/02/09 Javascript
JavaScript使用cookie记录临时访客信息的方法
2015/04/07 Javascript
javascript实现下拉提示选择框
2015/12/29 Javascript
js闭包引起的事件注册问题介绍
2016/03/29 Javascript
浅谈js中的延迟执行和定时执行
2016/05/31 Javascript
Ajax使用原生态JS验证用户名是否存在
2020/05/26 Javascript
Bootstrap缩略图的创建方法
2017/03/22 Javascript
微信小程序实现图片放大预览功能
2020/10/22 Javascript
在vscode里使用.vue代码模板的方法
2018/04/28 Javascript
js实现简单页面全屏
2019/09/17 Javascript
探索浏览器页面关闭window.close()的使用详解
2020/08/21 Javascript
在Django的模板中使用认证数据的方法
2015/07/23 Python
浅谈python中的数字类型与处理工具
2017/08/02 Python
Python判断一个三位数是否为水仙花数的示例
2018/11/13 Python
基于Python函数和变量名解析
2019/07/19 Python
python 处理微信对账单数据的实例代码
2019/07/19 Python
Python安装whl文件过程图解
2020/02/18 Python
英国最大的专业户外零售商:Mountain Warehouse
2018/06/06 全球购物
法国二手手袋、手表和奢侈珠宝购物网站:Collector Square
2018/07/05 全球购物
英国简约舒适女装品牌:Great Plains
2018/07/27 全球购物
高中运动会入场词
2014/02/14 职场文书
新疆民族团结演讲稿
2014/08/27 职场文书
迎新晚会主持词开场白
2015/05/28 职场文书
售房协议书范本
2015/08/11 职场文书
Python基础知识之变量的详解
2021/04/14 Python
python接口测试返回数据为字典取值方式
2022/02/12 Python