天天看点

一文详解小程序授权、登录、session_key和unionId

微信应用的一个很大的优势就在于使用过程中是不需要进行注册和显式登录的,大部分问题基本上可以一键解决。但是在授权、登录和获取用户信息的过程中都发生了哪些事情,今天我们就来讨论一下。这篇文章主要分析以下几个问题:

  • 授权和登录的意义
  • session_key 的作用
  • unionId 的作用,有哪些获取途径
  • 在应用中如何保存用户登录态

1

授权和登录的意义

首先必须要明白,授权和登录实际上是两个操作。

1.1 授权

那授权的作用是啥呢?从小程序官方文档中我们可以看到授权操作只需通过wx.authorize() 接口便可以完成,以下是文档中对授权操作的描述:

提前向用户发起授权请求。调用后会立刻弹窗询问用户是否同意授权小程序使用某项功能或获取用户的某些数据,但不会实际调用对应接口。如果用户之前已经同意授权,则不会出现弹窗,直接返回成功。

也就是说,授权过程实际上只是在小程序前端获得了操作部分wx 接口的访问许可,这个过程实际上是不会与开发者服务器发生任何关系的。那这些访问许可包含哪些内容呢?再来看微信官方提供的scope 列表:

一文详解小程序授权、登录、session_key和unionId

注:新版api已废弃wx.authorize()

1.2 登录

所谓的登录就是要让开发者服务器知道当前的用户是谁?在传统的web 应用中,我们必须要让用户输入账号和密码才能实现登录操作。但是在微信应用中,我们可以通过微信服务器来完成这个操作,获取到与当前用户对应的唯一标志(openId),具体操作实现流程如下:

wx.login()用来做登录的方法,调用接口获取登录凭证,code发送给后端用于置换session_key和openid等数据。每个用户相对于每个微信应用(公众号或者小程序)的openId 是唯一的,也就是说一个用户相对于不同的微信应用会存在不同的openId。

一文详解小程序授权、登录、session_key和unionId

这是小程序官方的一张登录流程图,现在就来解读一下这个流程

  • 前端wx.login()获取code,调用后端接口,将得到的code发送到后端
  • 后端调用微信接口,用appid+appsecret+code发送过去,置换到session_key+openid,以前是不能置换unionid的,但是现在在满足以下条件可以置换到unionid
  1. 微信开放平台下存在同主体的App、公众号、小程序
  2. 用户关注了某个相同主体公众号,或曾经在某个相同主体App、公众号上进行过微信登录授权 同时满足以上两个条件就能拿到用户unionid,这样一来,就能在wx.login()准确识别出用户是谁
  • 自定登录态与openid和session_key关联,实际就是生成一个与openid,session_key关联的token,下发给前端
  • 前端将后端下发的token存入缓存,在后面的接口请求中带上自定登录态

以上就是小程序的整个登录流程,可以看到其实并不是一定要wx.getUserInfo()才能拿到用户的信息,在特定的条件下,通过wx.login()的调用拿到unionId也能后端数据库里拿到用户信息。登录过程中涉及session_key和unionId,于是又引出了下面的问题。

2

session_key 的作用

那么,session_key在登录的过程中或者登录完成后起什么作用呢?一起来看一下。

2.1 wx.getUserInfo

首先来看一下wx.getUserInfo 这个api:

一文详解小程序授权、登录、session_key和unionId

在设置withCredentials 属性为true 的情况下,这个api 可以拿到encryptedData,iv 等敏感信息,encryptedData 需要使用session_key 进行解密,解密后可以拿到的数据如下:

一文详解小程序授权、登录、session_key和unionId

也就是说,session_key的作用之一是将小程序前端从微信服务器获取到的encryptedData 解密出来,获取到openId 和unionId等信息。

但是在1.2登录过程中可以看到开发者服务器是能够直接拿到用户的openId信息,而且unionId 也是有其他获取途径,所以session_key 在这里的作用看起来有点鸡肋。

2.2 getPhoneNumber

session_key 更重要的作用大概体现在获取用户手机方面(可能还包含其他敏感信息获取api)。

一文详解小程序授权、登录、session_key和unionId

从文档中可以看到getPhoneNumber 返回的用户数据是加密过的,只有使用session_key才能解密,而小程序前端没有session_key,所以无法获取到用户的手机,只能传到开发者服务器进行处理。

3

unionId 的作用,有哪些获取途径?

3.1、UnionID机制说明

如果公司拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。

Tip:unionid 用于识别同一主体下不同账号之间的用户。举例说明:就是公司有A订阅号,B服务号,同一个人关注A和B,会得到不同的OPENID,但是会得到相同的unionid。这样就可以识别到相同的用户,用于不同账号之间打通用户关系。

3.2、UnionID获取途径

必须有一个微信开放平台账号绑定了至少一个微信公众账号或者网站应用或者小程序,否则UnionID返回null。绑定了开发者帐号的小程序,可以通过下面3种途径获取UnionID。

方法一:调用接口wx.getUserInfo,从解密数据中获取UnionID。注意本接口需要用户授权,请开发者妥善处理用户拒绝授权后的情况。

方法二:如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号。开发者可以直接通过wx.login获取到该用户UnionID,无须用户再次授权。

方法三:如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用。开发者也可以直接通过wx.login获取到该用户UnionID,无须用户再次授权。

一文详解小程序授权、登录、session_key和unionId

4

在应用中如何保存用户登录态

保存用户登录态,一直以来都有两种解决方案:前端保存和后端保存。

4.1 后端保存

在1.2 步骤③ 中写session 的时候可以直接设定过期时间,定期通知小程序前端重新进行登录(wx.login)。

4.2 前端保存

因为session_key 存在时效性问题(毕竟是用来查看敏感信息),而小程序前端可以通过wx.checkSession() 来检查session_key 是否过期。所以可以通过这个来作为保存用户登录态的机制,这也是小程序文档中推荐的方法:

一文详解小程序授权、登录、session_key和unionId