-
Notifications
You must be signed in to change notification settings - Fork 362
WeDemo App交互时序说明文档
##目录
当App尚未登录服务器前,App与Server之间会经过一次握手建立登录前安全信道,时序图如下所示:
以下为详细说明:
-
AppClient本地通过一些随机算法生成一个32bytes的密钥psk(preSessionKey)。
-
AppClient通过向服务器特定path发送HTTP请求包,内容为用HardCode在AppClient的RSA公钥加密的psk.
-
AppServer用RSA私钥解密包获得psk,生成一个临时的用户标示符temp_uin并建立
temp_uin<->psk
的映射。 -
AppServer用psk作为密钥,将
temp_uin
AES加密,在末尾加上HMac-SHA256的MAC后用Base64 Encoding后返回给AppClient。 -
AppClient对回包进行Base64 Decode之后,验证MAC一致后用psk作为密钥进行AES解密获得temp_uin保存到内存中.
至此AppClient和AppServer之间的登录前安全信道建立完成,之后一直至使用登录票据登录AppServer之前,AppClient和AppServer都使用psk作为密钥加密报文,并把密文+HMac-SHA256的MAC进行Base64Encode,并带上temp_uin一并发送出去。
当用户点击“微信登录”按钮时,会触发利用微信SSO换取登录票据事件,此部分需在登录前安全信道中进行,时序图如下所示:
以下为详细说明:
-
AppClient通过微信SDK拉起微信客户端,用户通过在微信客户端同意授权后,返回一个code给AppClient。
-
AppClient用psk对codeAES加密,在末尾加上HMac-SHA256的MAC后进行Base64 Encode,连带temp_uin(明文)一并发给AppServer。
-
AppServer通过明文获得temp_uin并索引到psk,验证MAC一致并解密后获得code参数。
-
AppServer用存在本地的AppID,AppSecret以及code参数发向微信OpenServer请求Token信息。注意,这里AppSecret只能存在于AppServer中,不能让AppClient直接请求Token信息。
-
微信的OpenServer返回用户的OpenId,AccessToken及其有效期,RefreshToken及其有效期等信息。
-
AppServer根据OpenId查询Uin,若无则生成新的Uin和LoginTicket,并建立
OpenId<->Uin<->LoginTicket
的映射。 -
AppServer用psk对{LoginTicket, Uin}加密,在末尾加上HMac-SHA256的MAC后经过Base64 Encoding发送给AppClient。
-
AppClient收到并验证MAC一致后,解密Uin和LoginTicket并保存到本地。
当AppClient获得正式Uin和LoginTicket时,会触发通过登录票据登录AppServer事件,此部分跟安全信道无关,时序图如下所示 :
以下为详细说明:
-
AppClient本地通过一些随机算法生成一个32bytes的密钥temp_key。
-
AppClient用HardCode在AppClient的RSA公钥加密的temp_key, Uin, LoginTicket发送给服务器.
-
AppServer通过RSA私钥解密获得temp_key, Uin, LoginTicket, 之后尝试匹配Uin和LoginTicket并且检查LoginTicket是否过期。如果票据是很久之前(例如三个月之前的)生成的,或者最近没有使用过(例如一周没使用过),那么票据就是过期的。若检查都成功则生成一个密钥SK(SessionKey)和对应的过期时间expireTime,并建立
Uin<->SK
的映射。 -
AppServer用temp_key对{SK, expireTime}进行AES加密,在末尾加上HMac-SHA256的MAC后经过Base64 Encoding发送给AppClient。
-
AppClient收到并验证MAC一致后,用temp_key作为密钥解密获得SK和expireTime并保存到内存。
至此,AppClient和AppServer之间的正式安全信道建立完成,直至expireTime之前,AppClient和AppServer都使用SK作为密钥加密报文,并在密文末尾加上HMac-SHA256的MAC,用Base64Encoding后带上Uin(明文)一并发送出去。
当AppClient获得SK和expireTime时,会触发获得用户信息事件,此部分需在正式安全信道中进行,时序图如下所示 :
以下为详细说明:
-
AppClient用SK对{Uin,LoginTicket}加密,将密文末尾加上HMac-SHA256的MAC后,进行Base64 Encoding与Uin(明文)一同发给AppServer。
-
AppServer通过明文获得Uin并索引到SK,若SK已过期,则触发App登录态/SK过期子事件, 否则验证MAC一致并解密获得LoginTicket。之后查询Uin和LoginTicket是否匹配,若成功,则根据Uin查询获得用户OpenId等用户信息。
-
AppServer利用OpenId和AccessToken向WXOpenServer查询用户的微信信息。注意,这里AccessToken和RefreshToken只能存在于AppServer中,不能让AppClient直接请求微信用户信息。
-
若AccessToken未过期,WXOpenServer返回对应的微信用户信息,包括微信昵称,头像Url等,若已过期,则触发微信登录的Token过期子事件。
-
AppServer用SK对用户信息(包括昵称,头像,OpenId,AccessToken有效期,Refresh Token有效期)进行AES加密,在末尾加上HMac-SHA256的MAC后经过Base64Encoding发送给AppClient。
-
AppClient收到验证MAC一致后,用SK作为密钥解密获得用户信息并保存到内存中和展示在屏幕上。
当AppServer在获得用户信息子事件中发现SK过期时,会触发App登录态/SK过期事件。此部分只需要执行之前的子事件即可,是否为安全通道由具体子事件决定,时序图如下:
以下为详细说明:
-
AppClient发起GetUserInfoRequest或wxBindAppRequest或appBindWXRequest请求.
-
AppServer通过Uin索引到SK,并查找SK的有效期,发现SK已过期。
-
AppServer返回一个错误码标识SK已经过期。
-
AppClient收到错误码后重新执行使用登录票据登录并建立正式安全信道子事件.
-
AppClient重新发起GetUserInfoRequest或wxBindAppRequest或appBindWXRequest请求.
当AppServer在获得用户信息子事件中通过OpenId和AccessToken向WXOpenServer请求微信信息时,发现AccessToken过期,会触发微信登录的Token过期事件。此部分分为AccessToken过期和RefreshToken过期两种情况。以下为分别描述:
若只是AccessToken,AppServer需要用RefreshToken去刷新AccessToken。这部分与安全信道无关,时序图如下:
以下为详细说明:
-
AppServer在向WXOpenServer请求微信用户信息的过程中发现AccessToken过期.
-
AppServer向WXOpenServer发起刷新AccessToken请求,请求里带上AppId和RefreshToken。注意,这里AccessToken和RefreshToken只能存在于AppServer中,不能让AppClient直接刷新AccessToken。
-
WXOpenServer将新的AccessToken及其过期时间返回给AppServer。
-
AppServer刷新AccessToken,并更新有效期并再次请求用户的微信信息.
若AppServer在刷新AccessToken的过程中发现RefreshToken过期,则需要让AppClient重新进行微信授权以获得新的RefreshToken。此部分需在正式安全信道中进行,时序图为:
以下为详细说明:
-
AppClient向AppServer请求用户信息。
-
AppServer向WXOpenServer请求微信用户信息的过程中发现RefreshToken过期。
-
AppServer给AppServer返回一个错误码标识Refresh Token过期了。
-
AppClient收到错误码后重新触发利用微信SSO换取登录票据子事件。
-
AppClient重新触发使用登录票据登录并建立正式安全信道子事件并重新获取用户信息。