小程序授权&登录&sessionkey&unionid介绍
前言
微信小程序相比于普通的应用,很大的一个优势在于不需要进行注册和显式登录,大部分问题可以直接一键微信登录解决。
但是,在点击 “授权”、”登录” 的过程中,都做了那些事情呢?
1、获取用户登录凭证:小程序首先会调用微信提供的wx.login
接口,获取用户的登录凭证(code)。这个code是一个临时的、有时效性的字符串,用于后续的身份验证。
2、发送请求到开发者服务器:小程序将获取到的code发送到开发者自己的服务器。这一步是为了保护用户的隐私和安全,因为用户的微信敏感信息(如openid、session_key等)不会直接暴露给小程序。
3、开发者服务器与微信服务器交互:开发者服务器将code、小程序的AppID和AppSecret(这是开发者在微信公众平台注册小程序时获得的,用于证明开发者身份的密钥)一起发送给微信服务器进行校验。
4、微信服务器返回用户信息:如果校验通过,微信服务器会返回一个openid和一个session_key给开发者服务器。openid是用户在微信中的唯一标识,session_key是本次会话的密钥,用于后续加密用户数据的解密。
5、开发者服务器返回用户信息给小程序:开发者服务器可以将openid返回给小程序。小程序可以根据openid进行用户的唯一标识和业务处理。如果需要获取更多用户信息,如昵称、头像等,小程序还需要用户进行额外的授权操作。
6、用户授权操作:如果用户需要授权小程序获取更多的个人信息,小程序会展示一个授权界面,用户点击“授权”按钮后,小程序就可以获取到用户的基本信息了。
这些就是在微信小程序中点击“授权”或“登录”的过程中,主要发生的一系列操作。这样的设计既保证了用户信息的安全性,又简化了用户的登录流程,提高了用户体验。
下面通过四个方面主要说一下具体的细节:
- 授权和登录的意义
- sessionkey的作用
- unionid的作用,有哪些获取途径
- 在应用中如何保存用户登录态
授权和登录的意义
首先,在这块需要明确一下概念,授权 和 登录 是两个操作。
1. 授权
部分接口需要经过用户授权同意才能调用。把这些接口按使用范围分成多个 scope
,用户选择对 scope
来进行授权,当授权给一个 scope
之后,其对应的所有接口都可以直接使用。
此类接口调用时:
- 如果用户未接受或拒绝过此权限,会弹窗询问用户,用户点击同意后方可调用接口;
- 如果用户已授权,可以直接调用接口;
- 如果用户已拒绝授权,则不会出现弹窗,而是直接进入接口 fail 回调。
参考小程序开发文档开放能力 / 用户信息 / 授权 (qq.com)中,授权操作是通过**wx.authorize()**接口便可以完成
提前向用户发起授权请求。调用后会立刻弹窗询问用户是否同意授权小程序使用某项功能或获取用户的某些数据,但不会实际调用对应接口。如果用户之前已经同意授权,则不会出现弹窗,直接返回成功。
也就是说,授权过程实际上只是在小程序前端获得了操作部分wx 接口的访问许可,这个过程实际上是不会与开发者服务器发生任何关系的。
再来看微信官方提供的scope 列表:
wx.authorize(Object object)接口示例代码如下:
// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope |
2. 登录
所谓的登录就是要让开发者服务器知道当前的用户是谁?在传统的web 应用中,我们必须要让用户输入账号和密码才能实现登录操作。但是在微信应用中,我们可以通过微信服务器来完成这个操作,获取到与当前用户对应的唯一标志(**openId**)。
微信提供了两种方法 wx.login 和 wx.getUserProfile ,官方是推荐使用第二种因为第二种是必须要通过用户的授权才可以获取信息,而第一种则是直接获取。
wx.login:
wx.login()用来做登录的方法,调用接口获取登录凭证,code发送给后端用于置换session_key和openid等数据。每个用户相对于每个微信应用(公众号或者小程序)的openId 是唯一的,也就是说一个用户相对于不同的微信应用会存在不同的openId。
小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。
上图是小程序官方的一张登录流程图,可以简单说一下这个流程
1、调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
2、后端调用微信接口,用appid+appsecret+code发送过去,置换到session_key+openid,以前是不能置换unionid的,但是现在在满足以下条件可以置换到unionid
- 微信开放平台下存在同主体的App、公众号、小程序
- 用户关注了某个相同主体公众号,或曾经在某个相同主体App、公众号上进行过微信登录授权 同时满足以上两个条件就能拿到用户unionid,这样一来,就能在wx.login()准确识别出用户是谁
3、自定义登录态与openid和session_key关联,实际就是生成一个与openid,session_key关联的token,下发给前端
4、前端将后端下发的token存入缓存,在后面的接口请求中带上自定登录态
以上就是小程序的整个登录流程,可以看到在特定的条件下,通过wx.login()的调用拿到unionId也能在后端数据库里拿到用户信息。
wx.getUserInfo()/wx.getUserProfile():
功能描述:获取用户信息。页面产生点击事件(例如 button
上 bindtap
的回调中)后才可调用,每次请求都会弹出授权窗口,用户同意后返回 userInfo
。wx.getUserProfile
该接口用于替换 wx.getUserInfo
,详见 用户信息接口调整说明。
这块以wx.getUserInfo
为例,首先看一下这个API:
在设置withCredentials 属性为true 的情况下,这个api 可以拿到encryptedData,iv 等敏感信息,encryptedData 需要使用session_key 进行解密,解密后可以拿到的数据。
也就是说,session_key的作用之一是将小程序前端从微信服务器获取到的encryptedData 解密出来,获取到openId 和unionId等信息。
但是在wx.login()登录过程中可以看到开发者服务器是能够直接拿到用户的openId信息,而且unionId 也是有其他获取途径,所以session_key 在这里的作用看起来有点鸡肋。
具体session_key有什么作用,可以继续往下看。
sessionkey的作用
登录过程中涉及session_key和unionId,于是又引出了下面的问题。
session_key在登录的过程中或者登录完成后起什么作用呢?
前面说到在wx.getUserInfo()
中可以利用session_key 对encryptedData进行加解密,那具体在什么场景下会涉及呢???
【场景举例】
在使用微信小程序的时候,登录一般会提供 微信授权一键登录,这时候会弹窗,确认手机号,然后进行登录确认:
所以,session_key 一个重要的作用大概体现在获取用户手机方面(可能还包含其他敏感信息获取api)。
可以看到getPhoneNumber 返回的用户数据是加密过的,只有使用session_key才能解密,而小程序前端没有session_key,所以无法获取到用户的手机,只能传到开发者服务器进行处理。
unionId 的作用&获取途径
1. unionid机制说明
如果公司拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。
Tip:unionid 用于识别同一主体下不同账号之间的用户。举例说明:就是公司有A订阅号,B服务号,同一个人关注A和B,会得到不同的OPENID,但是会得到相同的unionid。这样就可以识别到相同的用户,用于不同账号之间打通用户关系。
2. UnionID获取途径
必须有一个微信开放平台账号绑定了至少一个微信公众账号或者网站应用或者小程序,否则UnionID返回null。绑定了开发者帐号的小程序,可以通过下面3种途径获取UnionID。
方法一:调用接口wx.getUserInfo,从解密数据中获取UnionID。注意本接口需要用户授权,请开发者妥善处理用户拒绝授权后的情况。
方法二:如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号。开发者可以直接通过wx.login获取到该用户UnionID,无须用户再次授权。
方法三:如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用。开发者也可以直接通过wx.login获取到该用户UnionID,无须用户再次授权。
在应用中如何保存登录态
保存用户登录态,一直以来都有两种解决方案:前端保存和后端保存。
1. 前端保存
在前面登录章节中自定义登录态写session 的时候可以直接设定过期时间,定期通知小程序前端重新进行登录(wx.login)。
2. 前端保存
因为session_key 存在时效性问题(毕竟是用来查看敏感信息),而小程序前端可以通过wx.checkSession() 来检查session_key 是否过期。所以可以通过这个来作为保存用户登录态的机制,这也是小程序文档中推荐的方法: