登录认证是一个完整应用必备的模块,除非你的应用程序不需要任何与用户相关的功能 比如hao123 这种静态导航网站一般不会涉及用户体系。

很多人在最初接触小程序登录功能时,会误认为以微信为入口的小程序使用微信登录,是一件理所当然、毫不费力的事儿,这是错误地将小程序理解成了微信的一部分。

小程序和微信是一种类似应用与平台的关系,小程序属于微信公众平台,同一个平台下还有微信公众号:

  • 在技术角度上,小程序与微信的关系比公众号更密切,因为公众号的文章本质上是一个 H5 网页,对微信底层的依赖比小程序弱;
  • 从产品角度上,二者与微信的关系一致,都是运行在微信平台上的第三方应用。

既然小程序是微信平台的第三方应用,那么在接入微信登录时就要严格遵守官方的接入规范。

而在互联网技术领域,对于支持第三方应用接入的平台,在登录授权上有一套标准的技术规范:OAuth 2.0。

OAuth 2.0 学起来比较枯燥,所以先从最容易理解的小程序登录流程讲起,理解其中涉及的各种术语之后,再理解 OAuth 2.0 规范就容易多了。

如何搭建微信小程序的登录流程?

我们认为以微信为宿主的小程序使用微信登录是一件理所当然的事儿,但其实小程序并没有强制要求只能使用微信登录。

小程序在登录方式的选择上有很高的自由度:使用微信登录仅仅是其中一个选择,你完全可以使用跟其他应用(网站、App)一样的登录方式,比如手机号、邮箱、用户名密码等。

既然如此,为什么我们一定要使用微信登录呢?因为除了便利性以外,微信登录更重要的优势是整合了微信庞大的生态系统,以及对于产品策略的加持。

小程序使用微信登录的优势

对于很多公司来说,微信小程序仅仅是其产品矩阵中的一个应用端(对于微信来说 小程序也只是一个三方应用),同时存在的还有网站、App 等应用端。

从生态系统的角度上, 相对于其他应用端,以微信为入口的小程序最大的优势是拥有微信完善的生态系统,用户使用微信登录后可以使用微信提供给小程序的各种平台级能力,比如订阅消息、微信支付等。

从用户体验的角度上, 用户能够很大程度上降低登录的复杂程度。想象一下,对比在小程序内用用户名密码登录和一键微信登录,哪种方式更容易被用户接受呢?结果不言而喻。

从产品策略的角度上, 使用微信登录小程序能够根据用户的来源,制定特殊的产品策略,比如对于小程序的用户发放专属的优惠券。

所以,你可以由此得出小程序使用微信登录的三个主要优势:

  • 融入微信生态;
  • 提高用户体验;
  • 制定产品策略。

这也说明了小程序接入微信登录的必要性,那它的登录流程是什么呢?

下面这张图清晰地描绘了微信小程序完整的登录流程、角色以及相关术语。

我们先熟悉一下这些内容,然后再结合这套流程学习 OAuth 2.0 规范。

说明

  1. 调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
  2. 调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 、 用户在微信开放平台帐号下的唯一标识UnionID(若当前小程序已绑定到微信开放平台帐号) 和 会话密钥 session_key。

    之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。

注意事项

  1. 会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。
  2. 临时登录凭证 code 只能使用一次

整个登录流程中描述了三种角色和六个术语,了解它们的定位和作用,是理解小程序登录流程的基础。

登录流程里的三个角色

客户端在整个登录流程中主要承担两种行为:

  • 作为整个流程的发起者,获取临时登录凭证 code。
  • 作为整个流程的终结者,存储登录态令牌 token。

不过客户端的所有信息和网络请求几乎都是可以被破解或拦截的,

所以出于安全的考虑,小程序登录流程中的一些接口被限制不能在客户端中直接调用,而是需要在服务端发起,开发者服务的工作便是处理这些安全敏感的网络请求。

体现为上图中使用code 获取 openid 和 session_key的请求,这个请求使用了微信提供的 auth.code2Session 接口。

而微信接口服务的工作对于开发者来说是不透明的,你需要做的仅仅是根据接口的规范,组装网络请求发送给它,然后根据返回的接口执行分发逻辑。

微信服务器会验证网络请求的合法性,对于合法请求下发密钥 session_key 和用户 openid。

登录流程的六个术语

code

它是在客户端(即小程序)内通过 wx.login API 获取的,然后通过 HTTP 请求发送给开发者服务器。code 的作用体现在“临时”两字上,它的有效期限仅有 5 分钟,并且仅能够使用一次(即请求一次 auth.code2Session 接口)。

appid

每个微信小程序在创建之后(即在微信公众平台注册并初始化完成)便同时生成了一appid,这个 ID 标记了小程序的唯一性,等同于网站的URL(经过备案的)、App 的包名等标记应用唯一性的信息。

appsecret

它是小程序的密钥,可以在微信公众平台的后台管理系统中获取。

appsecret 是非常私密的信息,所以微信在制定小程序登录的流程时,将携带此信息的网络请求限制在只能通过开发者服务器发送给微信接口服务,这样对于客户端来说是不可见的,进而降低了被泄露的可能性。

与appid 不同的是,appsecret 可以被重置,但每次重置之后,历史的 appsecret 便会失效,所以请谨慎操作。

openid

这里你要注意,很多开发者容易走入一个误区:误将 openid 理解为用户的唯一 ID。

这句话如果放在某个小程序的特定语境下是没有问题的,但是如果放在微信生态的全局角度上是错误的。

为什么呢? ---微信对于用户 openid 的定义是:

 
微信号在某个应用程序中的唯一 ID。这里的“某个应用程序”指的是小程序、公众号、接入开放平台的应用。微信生态中目前有公众平台和开放平台两种,其中公众平台又细分为小程序和公众号,开放平台可以接入网站、移动应用等。同一个微信号在不同的应用程序中有不同的 openid。

在微信生态下另外有一个标记微信号的唯一 ID:UnionId。这个 ID 跟应用程序无关。所以,可以简单地理解为 UnionId 与 appid 综合加密后的结果,见下图:

UnionId 通常用来关联在不同应用程序中各个 openid ,比如同一个微信号在小程序和公众号内需要配置同样的权限,仅通过 openid 无法实现,便需要获取此微信号的 UnionId。

虽然获取 UnionId 的流程并不在这节课的讨论范围之内,但我相信你在后续工作中一定会遇到处理 UnionId 和 openid 的场景,所以先了解一下没啥坏处。

session_key

session_key 是对用户数据进行加密签名的密钥,微信服务器使用它将用户的数据进行加密和解密。

你可以简单地将 session_key 理解为获取用户数据的“绿卡”,登录之后所有涉及访问微信服务器的请求一般都需要带上它,微信服务器会校验 session_key 的合法性。

其实到这一步(即拿到了 openid 和
session_key)已经完成了小程序的登录流程,但对于一个应用程序来说,用户进行登录操作应该是“一劳永逸”的,即登录过一次之后在一定时间之内的后续操作都不需要再次登录,用技术语言描述就是应该保存用户的登录态。这个时候就需要用到接下来的一个术语:token。

token

登录态是个逻辑词汇,token 可以理解为登录态的具象化、数据化。

在小程序的登录流程图中,你可以看出,token是由开发者服务器创建的一个字符串,而且需要跟 openid 和 session_key
相关联(其实这里并不是强制关联 openid,因为 openid 并不算是私密信息,可以放心地下发到客户端(即小程序)。但是
session_key 是非常私密的信息,一旦泄露有很大的安全隐患,所以强烈建议不要把它下发到客户端)。

在获取到 openid 和 session_key 之后,开发者服务器创建一个 token,然后与 openid 和session_key 进行关联,具体的方法根据服务器编程语言的不同有多种实现方案。

咱们以JavaScript 语言作为示例,可以创建一个对象,对象的 key 是 token 的值,value 是一个包含 openid 和 session_key 的对象,如下:

 
{
"token_1": {
"openid": "获取到的openid 1",
"session_key": "获取到的session_key 1"
},
"token_2": {
"openid": "获取到的openid 2",
"session_key": "获取到的session_key 2"
},
}

关联完成之后开发者服务器将 token下发到客户端,客户端保存在本地,后续的所有请求均需要携带此 token,携带的方法并没有既定的规范,可以通过 URL Query、HTTP Body、Header 等,但通常建议通过 Header 传递,这样相对来说更安全一些。

后续

讲到这儿,小程序接入微信登录的全部流程便讲解完成了,根据上面的内容我相信你能够搭建一套小程序登录流程。但是这就满足了吗?

我在最初搭建小程序登录流程时,也是先完成了这些内容的学习,但在完成了登录需求之后却并没有满足于仅仅知晓怎么搭建和使用,而是迫切地想进一步了解每个术语存在的意义,以及为什么登录流程被设计成这套形态。换句话说就是“知其然更知其所以然”。

我相信你一定也想更进一步丰富自己的知识储备,如果被我说中了,那么接下来我们就一起来学习小程序登录流程背后的 OAuth 2.0 规范吧。

OAuth 2.0 规范:知其然更知其所以然

OAuth 2.0 规范中的角色划分

咱们先思考一个问题:小程序登录之后如果需要访问用户的数据(比如昵称、地域、性别等)需要得到谁的授权?是微信?还是用户?

答案是用户。用户的数据虽然存放在微信的服务器之上,但是这些数据的所有权属于用户自己,而不是微信。这里其实引出了 OAuth 2.0 规范中的两个基本概念。

  • Resource Owner:资源所有者,即用户。
  • Resource Server:资源服务器,即微信。

而小程序在获取用户数据中的角色是作为微信平台的第三方应用程序,在 OAuth 2.0 规范中的术语为 Third-party application。

除了以上三种角色之外,OAuth 2.0规范中还有另外三种角色:

  • 小程序依托于微信提供的底层技术平台(即 01 讲中的双线程模型),微信为小程序提供了与用户(即Resource Owner)沟通的工具,它在 OAuth 2.0 规范中的角色被称为 User Agent(用户代理)。
  • 微信服务器不仅仅作为 Resource Server
    保存用户数据,同时在登录授权过程中又提供了HTTP服务以及授权认证功能,这两个功能的角色在 OAuth 2.0 规范中分别被称为 HTTP
    Service(HTTP服务提供商)和Authorization server(认证服务器)。

以上便是 OAuth 2.0 规范中的所有角色,为了加强了解,我们再梳理一遍:

  • Resource Owner(资源所有者):在小程序场景下代表小程序的用户。
  • Resource Server(资源服务器,即存放用户数据、资源的服务器):在小程序场景下这个角色由微信服务器承担。
  • Third-party application(第三方应用程序/又称客户端):在小程序场景下代表小程序。
  • User Agent(用户代理):在小程序场景下代表微信。
  • Authorization server(认证服务器):在小程序场景下,这个角色由微信服务器承担。
  • HTTP Service(HTTP 服务提供商):在小程序场景下,这个角色由微信服务器承担。

学到这儿,你有没有疑惑为什么 OAuth 2.0 规范中的角色与小程序登录流程中角色不一样?

其实,小程序登录流程中的三个角色是按照实体划分的,而 OAuth 2.0 规范的角色是按照功能划分的,同一个实体可以担任一种或多种功能。

在小程序登录流程中的 3 个实体角色中,微信服务器同时担任 Resource Server、Authorization server 和HTTP
Service 的功能;开发者服务器比较特殊,它即担任 HTTP Service 的功能,同时在认证流程中由于需要转发和关联
token,所以也充当了客户端的一部分功能。

而OAuth 2.0 规范如此分配角色,是为了规范一套严谨的授权流程。那么它到底解决了什么问题呢?

OAuth 2.0 规范要解决什么问题

先卖个关子,想一下这样的场景:

比如你向邻居借了衣架忘了还,某天邻居着急使用所才打电话向你要回,不巧的是你正在外地出差家里没人。

但好在你家的门锁是智能门锁,你可以将密码告诉邻居让他自己去你家里取。

但是你本着“防人之心不可无”的心理,担心邻居是否会趁机记下甚至修改你家的门锁密码。

左右为难的时候,你突然想起来你家的智能门锁可以创建临时密码,这种临时密码只能在 10 分钟之内有效,而且没有修改原本密码的权限。

所以,最终你在手机上创建了一个临时智能门锁的密码发给你的邻居。

OAuth 2.0 规范要解决的问题与上面提到的这个现实案例非常相似,简单概括就是:OAuth
2.0是一个授权机制,资源所有者告诉认证服务器,临时授予某个第三方应用访问资源服务器获取资源的权限,认证服务器给第三方应用颁发一个临时令牌,拥有这个令牌便可以获取资源数据,一旦令牌过期或失效便收回权限。

OAuth 2.0 规范中的令牌与小程序登录场景下的 token 作用是一致的,只不过 OAuth
规范只定义了令牌的作用,并没有限制它的具体使用方法,微信把 token 与 session_key 相关联,开发者服务器通过 token 取到
session_key 进而解密用户资源数据,这种使用方法是在遵循 OAuth 规范前提下的一种具体实践。

总结

我并不仅仅是告诉你如何搭建和使用微信小程序的登录流程,而是想通过这个流程引导你去学习它背后的原理知识。

小程序登录流程只是在小程序这一单一场景下的具体实践,而它背后的 OAuth 2.0 规范是在互联网业内通用的标准,以后不论是你想要接入其他第三方认证还是开发自己的认证系统,都需要遵守 OAuth2.0 规范才能够做到标准化、产品化。

通过这篇文章我希望你能够有以下收获:

  • 理解并学会搭建小程序的登录体系;
  • 熟悉 OAuth 2.0 规范,并了解授权认证的基本流程和相关术语

小程序登录与OAuth规范的更多相关文章

  1. ASP.NET WebAPI 双向token实现对接小程序登录逻辑

    最近在学习用asp.net webapi搭建小程序的后台服务,因为基于小程序端和后台二者的通信,不像OAuth(开放授权),存在第三方应用.所以这个token是双向的,一个是对用户的,一个是对接口的. ...

  2. 完整且易读的最新版小程序登录态和检验注册过没的app.js写法

    目录 0.可参考的官方页面 1.流程 2.app.js代码 3.java后台怎么通过code获取openId 0.可参考的官方页面 获取登录凭证:https://developers.weixin.q ...

  3. uni-app微信小程序登录授权

    微信小程序授权是非常简单和常用的功能,但为了方便,还是在此记录一下要点: 首先是需要用到一个授权按钮来触发获取用户信息授权: 关键在于 open-type 为 getUserInfo , 然后有个@g ...

  4. Spring Security 整合 微信小程序登录的思路探讨

    1. 前言 原本打算把Spring Security中OAuth 2.0的机制讲完后,用小程序登录来实战一下,发现小程序登录流程和Spring Security中OAuth 2.0登录的流程有点不一样 ...

  5. 微信小程序开发:python+sanic 实现小程序登录注册

    开发微信小程序时,接入小程序的授权登录可以快速实现用户注册登录的步骤,是快速建立用户体系的重要一步.这篇文章将介绍 python + sanic + 微信小程序实现用户快速注册登录全栈方案. 微信小程 ...

  6. spring mvc+redis实现微信小程序登录

    本文将详细的介绍微信小程序的登录流程以及在ssm框架下如何实现小程序用户登录 登录流程概要 主要的登录流程可以参考官方提供的一张流程图: 1.微信前台页面: 在微信版本更新之后,提高了安全机制,我们需 ...

  7. 做一个开源的小程序登录模块组件(token)

    先了解下SSO 对于单点登陆浅显一点的说就是两种,一种web端的基于Cookie.另一种是跨端的基于Token,一般想要做的都优先做Token吧,个人建议,因为后期扩展也方便哦. 小程序也是呢,做成t ...

  8. 微信小程序登录(包括获取不到unionid的情况)

    我们一般都是先获取到微信的 unionid,然后再通过 unionid 去登录自己的网站,就可以关联到用户在自己网站上的 user_id,但是在小程序登录中,有时候可以获取到 unionid,有时候获 ...

  9. django-微信小程序登录

    小程序登录逻辑前端通过调用wx.login()获取code, 将code和用户基本信息发送到后端,后端通过request.get向微信服务器发送get请求获取用户openid和session_key, ...

  10. 微信小程序登录流程

    小程序登录流程 参考 app.js需要做的 1,首先通过wx.login()拿到code,成功之后,发送数据,请求接口,把code发送给后端,换区openid,sessionKey,unionId,把 ...

随机推荐

  1. [转]CSS、LESS和SASS(SCSS)的区别以及Ruby Sass、LibSass、Node Sass、Dart Sass之间的关系

    随着前端开发的不断发展,CSS也逐渐延伸出了很多新的语言,less和Sass就是其中两种,下面我们就一起来看看它们到底有何区别. SASS和LESS SASS(英文全称:Syntactically A ...

  2. [转]worldwind在线加载google地图,或者基于墨卡托投影的切片地图

    package gis1; import java.net.MalformedURLException; import java.net.URL; import gov.nasa.worldwind. ...

  3. 字符串编码(ASCII, GBK, ANSI, Unicode(‘u‘), UTF-8编码)(转载)

    [版权声明]本篇文章以征得博主同意,再行转载. 出自[hxxjxw] 原文链接:https://blog.csdn.net/hxxjxw/article/details/90140663 目录 字符串 ...

  4. 怎么在 Linux 下运行 smart_rtmpd

    怎么在 Linux 下运行 smart_rtmpd 操作系统的准备 我们知道比较流行的 Linux 操作系统基本上分为两类,一类是以 Redhat 为基线的 Redhat, CentOS:另一类是 D ...

  5. 利用SDCC开源项目搭建C51编译平台

    下载sdcc 安装sdcc 安装sublime 新建编译系统输入以下内容 { "shell_cmd": "sdcc \"${file}\" " ...

  6. Linux 检查磁盘空间命令合集

    1. DF df 是检查Linux安装程序上可用分区空间的最常用的命令之一.可以使用"df -TH"以直观易读的格式打印分区类型和分区大小.此命令将显示每个部分的总可用空间.已用空 ...

  7. 一个超经典 WinForm,WPF 卡死问题的终极反思

    一:背景 1. 讲故事 写这篇文章起源于训练营里一位朋友最近在微信聊到他对这个问题使用了一种非常切实可行,简单粗暴的方式,并且也成功解决了公司里几个这样的卡死dump,如今在公司已是灵魂级人物,让我也 ...

  8. 冠军!天翼云在国际AI顶会大模型挑战赛中拔得头筹!

    6月7日,国际人工智能顶会CVPR 2023举办的第一届大模型挑战赛(CVPR 2023 Workshop on Foundation Model:1st foundation model chall ...

  9. [记录点滴] 小心 Hadoop Speculative 调度策略

    [记录点滴] 小心 Hadoop Speculative 调度策略 目录 [记录点滴] 小心 Hadoop Speculative 调度策略 [0x00] 摘要 [0x01] 缘由 [0x02] 代码 ...

  10. Centos7下oracle12c的安装与配置

    一.硬件资源配置(虚拟机) CentOS7@VMware Workstation 10 Pro,分配资源:CPU:2颗,内存:4GB,硬盘空间:20GB+30GB 二.软件环境配置 软件上传 xshe ...