點擊進(jìn)入原地址
小程序調(diào)用wx.login得到code.
調(diào)用接口獲取登錄憑證(code)進(jìn)而換取用戶登錄態(tài)信息,包括用戶的唯一標(biāo)識(openid) 及本次登錄的 會話密鑰(session_key)。用戶數(shù)據(jù)的加解密通訊需要依賴會話密鑰完成。
小程序調(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)給予客戶端反饋, 微信側(cè)返回錯誤則可判斷為惡意請求, 可以不返回. 微信文檔鏈接
這是一個 HTTP 接口,開發(fā)者服務(wù)器使用登錄憑證 code 獲取 session_key 和 openid。其中 session_key 是對用戶數(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計算signature, 并與小程序傳入的signature比較, 校驗signature的合法性, 不匹配則返回signature不匹配的錯誤. 不匹配的場景可判斷為惡意請求, 可以不返回. 微信文檔鏈接
通過調(diào)用接口(如 wx.getUserInfo)獲取敏感數(shù)據(jù)時,接口會同時返回 rawData、signature,其中 signature = sha1( rawData + session_key )
將 signature、rawData、以及用戶登錄態(tài)發(fā)送給開發(fā)者服務(wù)器,開發(fā)者在數(shù)據(jù)庫中找到該用戶對應(yīng)的 session-key,使用相同的算法計算出簽名 signature2 ,比對 signature 與 signature2 即可校驗數(shù)據(jù)的可信度。
使用第4步返回的session_key解密encryptData, 將解得的信息與rawData中信息進(jìn)行比較, 需要完全匹配, 解得的信息中也包括openid, 也需要與第4步返回的openid匹配. 解密失敗或不匹配應(yīng)該返回客戶相應(yīng)錯誤. 微信文檔鏈接
接口如果涉及敏感數(shù)據(jù)(如wx.getUserInfo當(dāng)中的 openid ),接口的明文內(nèi)容將不包含敏感數(shù)據(jù)。開發(fā)者如需要獲取敏感數(shù)據(jù),需要對接口返回的加密數(shù)據(jù)( encryptData )進(jìn)行對稱解密。 解密算法如下:
- 對稱解密使用的算法為 AES-128-CBC,數(shù)據(jù)采用PKCS#7填充。
- 對稱解密的目標(biāo)密文為 Base64_Decode(encryptData),
- 對稱解密秘鑰 aeskey = Base64_Decode(session_key), aeskey 是16字節(jié)
對稱解密算法初始向量 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. 加密算法可以參考微信對encryptData的加密算法. server應(yīng)該緩存session_key, 緩存的過期時間不應(yīng)該小于token的過期時間. 將openid, token返回給客戶端.
小程序每次業(yè)務(wù)請求都必須帶上openid和token, server驗證token的合法性: token能否被正常解密; 解密后的openid和傳入的openid是否一致; 解密后可得到token的生成時間, token是否過期. 全部校驗通過即可正常處理業(yè)務(wù)請求.