點(diǎn)擊進(jìn)入原地址
小程序調(diào)用wx.login得到code.
調(diào)用接口獲取登錄憑證(code)進(jìn)而換取用戶(hù)登錄態(tài)信息,包括用戶(hù)的唯一標(biāo)識(shí)(openid) 及本次登錄的 會(huì)話(huà)密鑰(session_key)。用戶(hù)數(shù)據(jù)的加解密通訊需要依賴(lài)會(huì)話(huà)密鑰完成。
小程序調(diào)用wx.getUserInfo得到rawData, signatrue, encryptData.
小程序調(diào)用server獲取token接口, 傳入code, rawData, signature, encryptData.
server調(diào)用微信提供的jsoncode2session接口獲取openid, session_key, 調(diào)用失敗應(yīng)給予客戶(hù)端反饋, 微信側(cè)返回錯(cuò)誤則可判斷為惡意請(qǐng)求, 可以不返回. 微信文檔鏈接
這是一個(gè) HTTP 接口,開(kāi)發(fā)者服務(wù)器使用登錄憑證 code 獲取 session_key 和 openid。其中 session_key 是對(duì)用戶(hù)數(shù)據(jù)進(jìn)行加密簽名的密鑰。為了自身應(yīng)用安全,session_key 不應(yīng)該在網(wǎng)絡(luò)上傳輸。
接口地址:"https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code"
server計(jì)算signature, 并與小程序傳入的signature比較, 校驗(yàn)signature的合法性, 不匹配則返回signature不匹配的錯(cuò)誤. 不匹配的場(chǎng)景可判斷為惡意請(qǐng)求, 可以不返回. 微信文檔鏈接
通過(guò)調(diào)用接口(如 wx.getUserInfo)獲取敏感數(shù)據(jù)時(shí),接口會(huì)同時(shí)返回 rawData、signature,其中 signature = sha1( rawData + session_key )
將 signature、rawData、以及用戶(hù)登錄態(tài)發(fā)送給開(kāi)發(fā)者服務(wù)器,開(kāi)發(fā)者在數(shù)據(jù)庫(kù)中找到該用戶(hù)對(duì)應(yīng)的 session-key,使用相同的算法計(jì)算出簽名 signature2 ,比對(duì) signature 與 signature2 即可校驗(yàn)數(shù)據(jù)的可信度。
使用第4步返回的session_key解密encryptData, 將解得的信息與rawData中信息進(jìn)行比較, 需要完全匹配, 解得的信息中也包括openid, 也需要與第4步返回的openid匹配. 解密失敗或不匹配應(yīng)該返回客戶(hù)相應(yīng)錯(cuò)誤. 微信文檔鏈接
接口如果涉及敏感數(shù)據(jù)(如wx.getUserInfo當(dāng)中的 openid ),接口的明文內(nèi)容將不包含敏感數(shù)據(jù)。開(kāi)發(fā)者如需要獲取敏感數(shù)據(jù),需要對(duì)接口返回的加密數(shù)據(jù)( encryptData )進(jìn)行對(duì)稱(chēng)解密。 解密算法如下:
- 對(duì)稱(chēng)解密使用的算法為 AES-128-CBC,數(shù)據(jù)采用PKCS#7填充。
- 對(duì)稱(chēng)解密的目標(biāo)密文為 Base64_Decode(encryptData),
- 對(duì)稱(chēng)解密秘鑰 aeskey = Base64_Decode(session_key), aeskey 是16字節(jié)
對(duì)稱(chēng)解密算法初始向量 iv = aeskey, 同樣是16字節(jié)
- rawData格式:
{ "nickName": "Band", "gender": 1, "language": "zh_CN", "city": "Guangzhou", "province": "Guangdong", "country": "CN", "avatarUrl": "http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0" }
- encryptData解密之后格式:
{ "openId": "OPENID", "nickName": "NICKNAME", "gender": 1, "city": "CITY", "province": "PROVINCE", "country": "COUNTRY", "avatarUrl": "AVATARURL", "unionId": "UNIONID" }
使用session_key作為密鑰, 加密至少包括openid, timestamp, random(隨機(jī)值), version(版本)的內(nèi)容, 得到token. 加密算法可以參考微信對(duì)encryptData的加密算法. server應(yīng)該緩存session_key, 緩存的過(guò)期時(shí)間不應(yīng)該小于token的過(guò)期時(shí)間. 將openid, token返回給客戶(hù)端.
小程序每次業(yè)務(wù)請(qǐng)求都必須帶上openid和token, server驗(yàn)證token的合法性: token能否被正常解密; 解密后的openid和傳入的openid是否一致; 解密后可得到token的生成時(shí)間, token是否過(guò)期. 全部校驗(yàn)通過(guò)即可正常處理業(yè)務(wù)請(qǐng)求.