《微信小程序七日谈》- 第五天:你可能要在登录功能上花费大力气
《微信小程序七日谈》系列文章:
本系列的文章并非初学教程,而是笔者在具体开发过程中遇到的问题以及部分解决方案。
前几篇文章的内容主要集中于小程序开发框架中的一些机制细节,基本上都是客户端层面的知识。随着小程序项目的不断深入,我们不得不面对一些需要客户端与服务端协同完成的需求,比如用户登录功能。
大多数的小程序都会有自身的用户体系,然而小程序必须要经过微信账户的验证授权,然后再与第三方服务器(也就是公司自己的服务器)通信实现用户的登录。这里面就涉及到微信账户信息与自身用户信息的耦合。下面就简单介绍一下我们项目目前实现用户登录的技术细节。
浏览器环境下登录的实现方案
在制定具体实现方案之前,我们首先思考一下用户登录功能需要注意哪些细节。通常来讲,实现用户登录功能需要注意以下两点:
- 登录状态保存;
- 安全验证。
登录状态保存就是登录成功后请求站内数据接口时无需再次登录,客户端与服务器按照既定的规则进行用户有效性验证。浏览器环境下的登录状态保存通常使用cookie实现,这种方案的实现原理是浏览器发出的http请求header中会携带客户端的cookie。如下图:

安全验证是为了应对流量劫持,防止中间人攻击,在我们的页面中插入乱七八糟的内容。大家可能会想到使用https来防止流量劫持。https可以应对绝大部分的应用场景,有效的防止流量劫持。但其实市场上有一些“黑科技”软件可以捕获并且解密https加密信息的,比如Fiddler。所以在https的基础上,再进行一层安全验证是还有必要的。
大家可以参考这篇文章了解fiddler解密https的知识。
自定义安全验证通常的方案是客户端与服务器约定好一个验证签名,客户端在发出http请求之前按照约定好的算法计算出一个签名字符串,并且在http请求中将计算签名的参数传递给服务器。服务器接收到请求之后,解析出签名字符串和客户端传递的计算参数,然后按照同样的算法计算出签名字符串,并将其与客户端的签名进行对比,完全一致则验证通过,否则返回验证未通过的数据。如下图:

上述流程成立的前提条件是:
- 浏览器可以获取到UA信息;
- 浏览器发出的http请求header中会携带UA信息,服务器可以获取。
那么这套方案在小程序平台上是否可以复用呢?答案是否定的。
小程序的限制
目前我们所知的小程序存在以下限制:
- 不支持cookie,所以使用cookie储存登录状态的方案不可行;
- http请求header不携带设备信息,服务器无法获取。
但是我们在吐槽小程序重重限制的同时得到了一个好消息:http请求可以自定义header。我们仿佛看到了解决问题的银弹。
使用自定义header传递敏感信息
登录识别信息在无法使用cookie传递的限制下只有两种传输途径:
- url query
- http header
小程序提供了获取设备信息的API,提供了在客户端计算签名字符串的参数。按前文提到的验证规则,客户端计算签名的参数必须传递给服务器才能保证两端计算的一致性。所以我们又面临了之前的抉择,是query还是header?
其实使用任何一种途径都可以完成需求,但是url query(通常称为data)的语义应该是与接口功能紧密相关的数据,并且http请求的header比url query数据更保密,所以我们团队最终采用header传递登录识别信息和设备信息的方案。
登录实现方案
确定信息的传递方式只是第一步,在小程序平台下实现自己的用户登录仍然有很多细节需要琢磨。我们首先看一下官方文档给出的第三方登录流程图:

官方文档给出的流程是实现第三方登录的基本流程,但是具体的登录功能中仍然有一些细节上的不同,比如:
- 手机验证码登录;
3rd_session和openId不能明文暴露给客户端,需要进行加密;- 登录状态保存的有效期;
- 用户登录的服务器与基础服务的服务器并不是同一台。
在小程序登录机制的基础上,我们团队在制定安全登录功能时最终采用了如下方案:

对比微信官方的登录流程图,有以下几个细节:
3rd_session和openId不直接暴露给客户端,而是通过可逆的加密算法进行加密后,组合成token暴露给客户端;- 第一次请求基础功能服务器时并不验证签名,此次请求的目的是从微信服务器获取
3rd_session和openId并且加密后返回客户端,以便后续请求使用; - 第二次请求的目标是用户服务器,携带token的sign。用户服务器首先会进行签名验证和手机验证码校验;
- 验证通过后解析
token获取3rd_session和openId,然后与uid结合重新计算token。最后将uid和token一并返回给客户端。
用户登录成功后,客户端将uid和token储存在本地,以便后续请求数据接口使用。
客户端储存token和uid的方式可以采用storage或者
app.globalData。
数据接口的请求验证方案
数据接口是在用户登录成功之后才可以进行请求,相比较登录功能,数据接口的请求验证方案要简单很多。如下图:

接口请求只需验证sign以及token即可,如果token错误或者已过期,则返回客户端重新登录的标识。
总结
想在微信小程序中实现自己的用户体系需要花费一些力气,每个公司都有自身的用户登录验证体系,同时还要考虑安全性和状态保存问题。在小程序不支持cookie、http请求header不携带设备信息等限制下,实现登录功能的各种细节都需要采用一些折中的手段。而且往往这些方案显得有些臃肿并且难以维护,非常考验开发者的抽象能力。
本篇文章阐述的是笔者团队目前采用的登录实现方案,并非最佳实践,许多细节仍需打磨。希望可以给大家一些参考。
《微信小程序七日谈》- 第五天:你可能要在登录功能上花费大力气的更多相关文章
- 《微信小程序七日谈》- 第四天:页面路径最多五层?导航可以这么玩
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...
- 《微信小程序七日谈》- 第二天:你可能要抛弃原来的响应式开发思维
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 上篇文 ...
- 《微信小程序七日谈》- 第一天:人生若只如初见
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...
- 《微信小程序七日谈》- 第六天:小程序devtool隐藏的秘密
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...
- 《微信小程序七日谈》- 第七天:不要捡了芝麻丢了西瓜
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...
- 《微信小程序七日谈》- 第三天:玩转Page组件的生命周期
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 前两篇 ...
- 微信小程序把玩(五)页面生命周期
原文:微信小程序把玩(五)页面生命周期 这里只要熟悉页面的基本生命周期即可,业务在指定生命周期函数内书写. 以下是官网给出的生命周期函数方法和状态图 上面的生周期函数图对于做Android 或者IOS ...
- 微信小程序从零开始开发步骤(四)自定义分享的功能
上一章节,实现了小程序的底部导航的功能,这一节开始实现一些简单的功能.本章节介绍的是小程序的自定义分享的功能. 可以分享小程序的任何一个页面给好友或群聊.注意是分享给好友或群聊,并没有分享到朋友圈.一 ...
- 1个多商户、多平台版 微信小程序(多商户、多平台版),影城行业、影业连锁 多商户、多平台版微信小程序。(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本)
1个 影城行业 微信小程序(多商户.多平台版), 影业连锁 多商户.多平台版微信小程序.(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本) 资讯QQ: 876635409 ...
随机推荐
- tornado settings想到的
今天有足够多的时间来看看Tornado中RequestHandler和Application这两个类的关系. 昨天想要调用settings中的内容,找了好半天不知道怎么在handler中使用setti ...
- SQL点滴25—T-SQL面试语句,练练手
原文:SQL点滴25-T-SQL面试语句,练练手 1. 用一条SQL语句查询出每门课都大于80分的学生姓名 name kecheng fenshu 张三 语文 81张三 ...
- SuspendLayout()了解方法
SuspendLayout()暂时挂起的布局逻辑控制(msdn),它ResumeLayout()在会同.我的理解是,使用SuspendLayout()让整个窗体站,等到所有的东西都设置齐全,然后Re ...
- mysql查询字段值为数字
原文:mysql查询字段值为数字 我想查询字段值为数字的sql如下:select * from tj_item_result where tj_value REGEXP '^[0-9]'
- 为ASP.NET MVC应用程序创建更复杂的数据模型
为ASP.NET MVC应用程序创建更复杂的数据模型 2014-05-07 18:27 by Bce, 282 阅读, 1 评论, 收藏, 编辑 这是微软官方教程Getting Started wit ...
- 使用shell+awk完成Hive查询结果格式化输出
好久不写,一方面是工作原因,有些东西没发直接发,另外的也是习惯给丢了,内因所致.今天是个好日子,走起! btw,实际上这种格式化输出应该不只限于某一种需求,差不多是通用的. 需求: --基本的:当前H ...
- iOS基础 - 数据存取
一.iOS应用数据存储的常用方式 XML属性列表(plist)归档 Preference(偏好设置) NSKeyedArchiver归档 SQLite3 Core Data 二.应用沙盒 每个iOS应 ...
- 附加被分离DB
如何附加被分离的质疑数据库? 简介 有些时间,由于日志损坏等原因,导致了数据库质疑.如果此时你分离了数据库,那你会发现你无法再附加上数据库,那后果还是很严重的.因此本文提供了一种方式,可以使得当数 ...
- Win 内存映射和堆栈
内存映射和堆栈 内存映射文件 内存映射文件可以用于3个不同的目的: 系统使用内存映射文件,以便加载和执行.exe和DLL文件.这可以大大节省页文件空间和应用程序启动运行所需的时间. 可以使用内存映射文 ...
- D5
今天的题目跟前几天的比起来简单了许多 由于T1没有开long long 所以T1全部WA掉了...只悲催的A了第二题 T1:多重背包 其实这一题我真心不会,DP各种弱,简直欲哭无泪... 不过认真的看 ...