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

  1. 第一天:人生若只如初见
  2. 第二天:你可能要抛弃原来的响应式开发思维
  3. 第三天:玩转Page组件的生命周期
  4. 第四天:页面路径最多五层?导航可以这么玩
  5. 第五天:你可能要在登录功能上花费大力气

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

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

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

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

在制定具体实现方案之前,我们首先思考一下用户登录功能需要注意哪些细节。通常来讲,实现用户登录功能需要注意以下两点:

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

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

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

大家可以参考这篇文章了解fiddler解密https的知识。

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

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

  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不携带设备信息等限制下,实现登录功能的各种细节都需要采用一些折中的手段。而且往往这些方案显得有些臃肿并且难以维护,非常考验开发者的抽象能力。

本篇文章阐述的是笔者团队目前采用的登录实现方案,并非最佳实践,许多细节仍需打磨。希望可以给大家一些参考。

《微信小程序七日谈》- 第五天:你可能要在登录功能上花费大力气的更多相关文章

  1. 《微信小程序七日谈》- 第四天:页面路径最多五层?导航可以这么玩

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...

  2. 《微信小程序七日谈》- 第二天:你可能要抛弃原来的响应式开发思维

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 上篇文 ...

  3. 《微信小程序七日谈》- 第一天:人生若只如初见

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 微信小 ...

  4. 《微信小程序七日谈》- 第六天:小程序devtool隐藏的秘密

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...

  5. 《微信小程序七日谈》- 第七天:不要捡了芝麻丢了西瓜

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩: 第五 ...

  6. 《微信小程序七日谈》- 第三天:玩转Page组件的生命周期

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 前两篇 ...

  7. 微信小程序把玩(五)页面生命周期

    原文:微信小程序把玩(五)页面生命周期 这里只要熟悉页面的基本生命周期即可,业务在指定生命周期函数内书写. 以下是官网给出的生命周期函数方法和状态图 上面的生周期函数图对于做Android 或者IOS ...

  8. 微信小程序从零开始开发步骤(四)自定义分享的功能

    上一章节,实现了小程序的底部导航的功能,这一节开始实现一些简单的功能.本章节介绍的是小程序的自定义分享的功能. 可以分享小程序的任何一个页面给好友或群聊.注意是分享给好友或群聊,并没有分享到朋友圈.一 ...

  9. 1个多商户、多平台版 微信小程序(多商户、多平台版),影城行业、影业连锁 多商户、多平台版微信小程序。(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本)

    1个 影城行业 微信小程序(多商户.多平台版), 影业连锁 多商户.多平台版微信小程序.(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本) 资讯QQ: 876635409  ...

随机推荐

  1. 清除css、javascript及背景图在浏览器中的缓存

    在实际项目开发过过程中,页面是上传到服务器上的.而为了减少服务器的压力,让用户少加载,浏览器会将图片.css.js缓存到本地中,以便下次访问网站时使用.这样做不仅减少了服务器的压力,并且也减少了用户的 ...

  2. 用lucene.net根据关键字检索本地word文档

    目前在做一个winform小软件,其中有一个功能是能根据关键字检索本地保存的word文档.第一次是用com读取word方式(见上一篇文章),先遍历文件夹下的word文档,读取每个文档时循环关键字查找, ...

  3. Grub启动配置文件

    和许多其他linux发行版一样,Fedora使用Grub作为32位和64位X86系统的启动加载器(bootloader).grub的配置文件主要是/boot/grub/grub.conf,而/boot ...

  4. leetcode第十题--Regular Expression Matching

    Problem:Implement regular expression matching with support for '.' and '*'. '.' Matches any single c ...

  5. Retrofit相关资料

    高速Android开发系列网络篇之Retrofithttp://www.w3c.com.cn/%E5%BF%AB%E9%80%9Fandroid%E5%BC%80%E5%8F%91%E7%B3%BB% ...

  6. JavaScipt中对DOM的理解

    一.理解DOM 浏览器通过文档对象模型DOM使JavaScript程序可以访问页面上的元素,而DOM是页面上XHTML中文档正文标题.段落.列表.样式ID.class以及所有其他出现的数据的一个内部表 ...

  7. .Net中批量更新或添加数据

    方法一:使用SqlBulkCopy实现批量更新或添加数据. SqlBulkCopy类一般只能用来将数据批量插入打数据库中,如果数据表中设置了主键,出现重复数据的话会报错,如果没有设置主键,那么将会添加 ...

  8. unique_ptr简谈

    看到文章里的同学留言说到unique_ptr,这两天看了一下cplusplus提供的reference才知道这个东西是c++11的新特性,对c++11的新特性不是很了解,花时间了解了下unique_p ...

  9. 序列化(ObjectOutputStream和ObjectInputStream)(切记:out是输出到本地中,in是输入到程序中)

    注意:序列化自定义类必须实现一个接口Serializable,在c#中序列化自定义类是使用特性也就是[Serializable] //要实现序列化的类 public class Student imp ...

  10. web 富文本编辑器总结

    前言 富文本编辑器,就是除了能输入不同的文本之外,还可以之间粘贴图画等其他的多媒体信息.也可说是所见即所得的编辑器. 目前可以使用的编辑器有很多, 在网络上有找到这样一份比较表格: 编辑器 产地 稳定 ...