《微信小程序七日谈》- 第五天:你可能要在登陆功能上花费大力气

《微信小程序七日谈》系列文章:html

  1. 第一天:人生若只如初见
  2. 次日:你可能要抛弃原来的响应式开发思惟
  3. 第三天:玩转Page组件的生命周期
  4. 第四天:页面路径最多五层?导航能够这么玩
  5. 第五天:你可能要在登陆功能上花费大力气
  6. 第六天:小程序devtool隐藏的秘密;
  7. 第七天:不要捡了芝麻丢了西瓜

本系列的文章并不是初学教程,而是笔者在具体开发过程当中遇到的问题以及部分解决方案。算法

前几篇文章的内容主要集中于小程序开发框架中的一些机制细节,基本上都是客户端层面的知识。随着小程序项目的不断深刻,咱们不得不面对一些须要客户端与服务端协同完成的需求,好比用户登陆功能。小程序

大多数的小程序都会有自身的用户体系,然而小程序必需要通过微信帐户的验证受权,而后再与第三方服务器(也就是公司本身的服务器)通讯实现用户的登陆。这里面就涉及到微信帐户信息与自身用户信息的耦合。下面就简单介绍一下咱们项目目前实现用户登陆的技术细节。微信小程序

浏览器环境下登陆的实现方案

在制定具体实现方案以前,咱们首先思考一下用户登陆功能须要注意哪些细节。一般来说,实现用户登陆功能须要注意如下两点:api

  1. 登陆状态保存;
  2. 安全验证。

登陆状态保存就是登陆成功后请求站内数据接口时无需再次登陆,客户端与服务器按照既定的规则进行用户有效性验证。浏览器环境下的登陆状态保存一般使用cookie实现,这种方案的实现原理是浏览器发出的http请求header中会携带客户端的cookie。以下图:
浏览器

安全验证是为了应对流量劫持,防止中间人攻击,在咱们的页面中插入乱七八糟的内容。你们可能会想到使用https来防止流量劫持。https能够应对绝大部分的应用场景,有效的防止流量劫持。但其实市场上有一些“黑科技”软件能够捕获而且解密https加密信息的,好比Fiddler。因此在https的基础上,再进行一层安全验证是还有必要的。安全

你们能够参考这篇文章了解fiddler解密https的知识。服务器

自定义安全验证一般的方案是客户端与服务器约定好一个验证签名,客户端在发出http请求以前按照约定好的算法计算出一个签名字符串,而且在http请求中将计算签名的参数传递给服务器。服务器接收到请求以后,解析出签名字符串和客户端传递的计算参数,而后按照一样的算法计算出签名字符串,并将其与客户端的签名进行对比,彻底一致则验证经过,不然返回验证未经过的数据。以下图:
微信

上述流程成立的前提条件是:cookie

  1. 浏览器能够获取到UA信息;
  2. 浏览器发出的http请求header中会携带UA信息,服务器能够获取。

那么这套方案在小程序平台上是否能够复用呢?答案是否认的。

小程序的限制

目前咱们所知的小程序存在如下限制:

  • 不支持cookie,因此使用cookie储存登陆状态的方案不可行;
  • http请求header不携带设备信息,服务器没法获取。

可是咱们在吐槽小程序重重限制的同时获得了一个好消息:http请求能够自定义header。咱们仿佛看到了解决问题的银弹。

使用自定义header传递敏感信息

登陆识别信息在没法使用cookie传递的限制下只有两种传输途径:

  1. url query
  2. http header

小程序提供了获取设备信息的API,提供了在客户端计算签名字符串的参数。按前文提到的验证规则,客户端计算签名的参数必须传递给服务器才能保证两端计算的一致性。因此咱们又面临了以前的抉择,是query仍是header?

其实使用任何一种途径均可以完成需求,可是url query(一般称为data)的语义应该是与接口功能紧密相关的数据,而且http请求的header比url query数据更保密,因此咱们团队最终采用header传递登陆识别信息和设备信息的方案。

登陆实现方案

肯定信息的传递方式只是第一步,在小程序平台下实现本身的用户登陆仍然有不少细节须要琢磨。咱们首先看一下官方文档给出的第三方登陆流程图:

官方文档给出的流程是实现第三方登陆的基本流程,可是具体的登陆功能中仍然有一些细节上的不一样,好比:

  • 手机验证码登陆;
  • 3rd_sessionopenId不能明文暴露给客户端,须要进行加密;
  • 登陆状态保存的有效期;
  • 用户登陆的服务器与基础服务的服务器并非同一台。

在小程序登陆机制的基础上,咱们团队在制定安全登陆功能时最终采用了以下方案:

对比微信官方的登陆流程图,有如下几个细节:

  1. 3rd_sessionopenId不直接暴露给客户端,而是经过可逆的加密算法进行加密后,组合成token暴露给客户端;
  2. 第一次请求基础功能服务器时并不验证签名,这次请求的目的是从微信服务器获取3rd_sessionopenId而且加密后返回客户端,以便后续请求使用;
  3. 第二次请求的目标是用户服务器,携带token的sign。用户服务器首先会进行签名验证和手机验证码校验;
  4. 验证经过后解析token获取3rd_sessionopenId,而后与uid结合从新计算token。最后将uid和token一并返回给客户端。

用户登陆成功后,客户端将uid和token储存在本地,以便后续请求数据接口使用。

客户端储存token和uid的方式能够采用storage或者app.globalData

数据接口的请求验证方案

数据接口是在用户登陆成功以后才能够进行请求,相比较登陆功能,数据接口的请求验证方案要简单不少。以下图:

接口请求只需验证sign以及token便可,若是token错误或者已过时,则返回客户端从新登陆的标识。

总结

想在微信小程序中实现本身的用户体系须要花费一些力气,每一个公司都有自身的用户登陆验证体系,同时还要考虑安全性和状态保存问题。在小程序不支持cookie、http请求header不携带设备信息等限制下,实现登陆功能的各类细节都须要采用一些折中的手段。并且每每这些方案显得有些臃肿而且难以维护,很是考验开发者的抽象能力。

本篇文章阐述的是笔者团队目前采用的登陆实现方案,并不是最佳实践,许多细节仍需打磨。但愿能够给你们一些参考。

相关文章
相关标签/搜索