登入官方說明html
小程序能夠經過微信官方提供的登陸能力方便地獲取微信提供的用戶身份標識,快速創建小程序內的用戶體系。前端
登陸流程時序算法
說明:編程
以後開發者服務器能夠根據用戶標識來生成自定義登陸態,用於後續業務邏輯中先後端交互時識別用戶身份。json
注意:小程序
session_key
是對用戶數據進行 加密簽名 的密鑰。爲了應用自身的數據安全,開發者服務器不該該把會話密鑰下發到小程序,也不該該對外提供這個密鑰。兄弟們,是否是很簡單,一看就會?我知道大家的回答以下圖,可是不要慌,咱們詳細講每一步後端
小程序端執行wx.login後在回調函數中就能拿到上圖的code,而後把這個code傳給咱們後端程序,後端拿到這個這個code後,能夠請求code2Session接口拿到用的openid和session_key,openid是用戶在微信中惟一標識,咱們就能夠把這個兩個值(val)存起來,而後返回一個鍵(key)給小程序端,下次小程序請求咱們後端的時候,帶上這個key,咱們就能找到這個val,就能夠,這樣就把登入作好了。api
調用接口獲取登陸憑證(code)。經過憑證進而換取用戶登陸態信息,包括用戶的惟一標識(openid)及本次登陸的會話密鑰(session_key)等。用戶數據的加解密通信須要依賴會話密鑰完成。更多使用方法詳見 小程序登陸。安全
參數服務器
Object object
屬性 | 類型 | 默認值 | 必填 | 說明 | 最低版本 |
---|---|---|---|---|---|
timeout | number | 否 | 超時時間,單位ms | 1.9.90 | |
success | function | 否 | 接口調用成功的回調函數 | ||
fail | function | 否 | 接口調用失敗的回調函數 | ||
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
object.success 回調函數
參數
Object res
屬性 | 類型 | 說明 |
---|---|---|
code | string | 用戶登陸憑證(有效期五分鐘)。開發者須要在開發者服務器後臺調用 code2Session,使用 code 換取 openid 和 session_key 等信息 |
示例代碼
wx.login({ success(res) { if (res.code) { // 發起網絡請求 wx.request({ url: 'https://test.com/onLogin', data: { code: res.code }, success: function (res) { wx.setStorageSync('login_key', res.data.data.login_key); } }) } else { console.log('登陸失敗!' + res.errMsg) } } })
本接口應在服務器端調用,詳細說明參見服務端API。
登陸憑證校驗。經過 wx.login() 接口得到臨時登陸憑證 code 後傳到開發者服務器調用此接口完成登陸流程。更多使用方法詳見 小程序登陸。
請求地址
GET https://api.weixin.qq.com/sns/jscode2sessionappid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
請求參數
屬性 | 類型 | 默認值 | 必填 | 說明 |
---|---|---|---|---|
appid | string | 是 | 小程序 appId | |
secret | string | 是 | 小程序 appSecret | |
js_code | string | 是 | 登陸時獲取的 code | |
grant_type | string | 是 | 受權類型,此處只需填寫 authorization_code |
返回值
Object
返回的 JSON 數據包
屬性 | 類型 | 說明 |
---|---|---|
openid | string | 用戶惟一標識 |
session_key | string | 會話密鑰 |
unionid | string | 用戶在開放平臺的惟一標識符,在知足 UnionID 下發條件的狀況下會返回,詳見 UnionID 機制說明。 |
errcode | number | 錯誤碼 |
errmsg | string | 錯誤信息 |
errcode 的合法值
值 | 說明 |
---|---|
-1 | 系統繁忙,此時請開發者稍候再試 |
0 | 請求成功 |
40029 | code 無效 |
45011 | 頻率限制,每一個用戶每分鐘100次 |
說完上面的登入後,咱們是否是尚未用到上面的session_key?這個就是在用戶受權的時候用的,用來解密用戶的數據,還要解密?是的你沒有聽錯,不要慌,下面給你解釋
後端獲取微信用戶信息流程
微信官方:忘了告訴你,session_key還會過時的,是的,沒錯就是這樣坑爹。
個人回覆:我就是頭鐵,我無論session_key過時,會帶來什麼樣的後果呢?
微信官方:對不起,你頭鐵沒有,你後端程序沒法用戶受權的數據,就問你氣不氣?
個人回覆:好的,你牛逼,我能夠接收你session_key過時,可是你要告訴我怎麼判斷他是過時的吧?怎麼獲取新的session_key吧?
微信官方:仍是要按照個人要求來吧?看你這麼可憐,告訴你吧,用wx.checkSession判斷是否過時,若是過時就重寫登入吧!獲取新的code,後端在去請求code2Session獲取新的session_key
個人回覆:好的,謝謝你sb
檢查登陸態是否過時。
經過 wx.login 接口得到的用戶登陸態擁有必定的時效性。用戶越久未使用小程序,用戶登陸態越有可能失效。反之若是用戶一直在使用小程序,則用戶登陸態一直保持有效。具體時效邏輯由微信維護,對開發者透明。開發者只須要調用 wx.checkSession 接口檢測當前用戶登陸態是否有效。
登陸態過時後開發者能夠再調用 wx.login 獲取新的用戶登陸態。調用成功說明當前 session_key 未過時,調用失敗說明 session_key 已過時。更多使用方法詳見 小程序登陸。
參數
Object object
屬性 | 類型 | 默認值 | 必填 | 說明 |
---|---|---|---|---|
success | function | 否 | 接口調用成功的回調函數 | |
fail | function | 否 | 接口調用失敗的回調函數 | |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
示例代碼
wx.checkSession({ success() { // session_key 未過時,而且在本生命週期一直有效 }, fail() { // session_key 已經失效,須要從新執行登陸流程 wx.login() // 從新登陸 } })
微信官方:你要獲取用的信息?我告訴你哈,若是要獲取的話,要通過用戶贊成的。
個人回覆:sb,我怎麼知道他是否受權過呢?若是沒有受權,我怎麼讓他受權?
**微信官方:你好,你能夠調用wx.getSetting來判斷,用戶是否受權,若是沒有受權,你要讓他點擊按鈕,調起受權頁面。用戶點擊贊成受權之後*,你就能夠調用wx.getUserInfo接口獲取數據了**
個人回覆:媽的,怎麼這麼麻煩?
微信官方:對不起,大佬,沒有辦法啊,咱們要保護用戶的信息安全啊
個人回覆:哦
基礎庫 1.2.0 開始支持,低版本需作兼容處理。
獲取用戶的當前設置。返回值中只會出現小程序已經向用戶請求過的權限。
參數
Object object
屬性 | 類型 | 默認值 | 必填 | 說明 |
---|---|---|---|---|
success | function | 否 | 接口調用成功的回調函數 | |
fail | function | 否 | 接口調用失敗的回調函數 | |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
object.success 回調函數
參數
Object res
屬性 | 類型 | 說明 |
---|---|---|
authSetting | AuthSetting | 用戶受權結果 |
示例代碼
wx.getSetting({ success(res) { console.log(res.authSetting) //部分結果,若是爲true,則表示該用戶對這項權限以及受權,若是沒有受權,咱們這須要經過button按鈕讓用戶受權 // res.authSetting = { // "scope.userInfo": true, // "scope.userLocation": true // } } })
注意事項
wx.authorize({scope: "scope.userInfo"})
,不會彈出受權窗口,請使用 <button_open-type="getUserInfo">
scope.userLocation
時必須配置地理位置用途說明。微信官方:當你小程序端調用咱們wx.getUserInfo的時候,咱們會返回你用的基本信息。
個人回覆:什麼是基本信息,哪些是敏感信息?我後端怎麼獲取呢?
微信官方:好比openid這些,大佬,你又兩種方法,第一:你能夠將這些基本信息傳到後端,第二: 你能夠講getUserInfo中的 iv,encryptedData傳給後端解密,機密後就能獲取到用戶的敏感信息了
個人回覆:好的,我後端怎麼解密呢?用什麼解密呢?
微信官方:你登入的時候不是,後端不是存了session_key嗎?加上這些數據,就能夠解密了
個人回覆:哦
調用前須要 用戶受權 scope.userInfo。
獲取用戶信息。
參數
Object object
屬性 | 類型 | 默認值 | 必填 | 說明 |
---|---|---|---|---|
withCredentials | boolean | 否 | 是否帶上登陸態信息。當 withCredentials 爲 true 時,要求此前有調用過 wx.login 且登陸態還沒有過時,此時返回的數據會包含 encryptedData, iv 等敏感信息;當 withCredentials 爲 false 時,不要求有登陸態,返回的數據不包含 encryptedData, iv 等敏感信息。 | |
lang | string | en | 否 | 顯示用戶信息的語言 |
success | function | 否 | 接口調用成功的回調函數 | |
fail | function | 否 | 接口調用失敗的回調函數 | |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
object.lang 的合法值
值 | 說明 |
---|---|
en | 英文 |
zh_CN | 簡體中文 |
zh_TW | 繁體中文 |
object.success 回調函數
參數
Object res
屬性 | 類型 | 說明 |
---|---|---|
userInfo | UserInfo | 用戶信息對象,不包含 openid 等敏感信息 |
rawData | string | 不包括敏感信息的原始數據字符串,用於計算簽名 |
signature | string | 使用 sha1( rawData + sessionkey ) 獲得字符串,用於校驗用戶信息,詳見 用戶數據的簽名驗證和加解密 |
encryptedData | string | 包括敏感數據在內的完整用戶信息的加密數據,詳見 用戶數據的簽名驗證和加解密 |
iv | string | 加密算法的初始向量,詳見 用戶數據的簽名驗證和加解密 |
接口調整說明
在用戶未受權過的狀況下調用此接口,將再也不出現受權彈窗,會直接進入 fail 回調(詳見《公告》)。在用戶已受權的狀況下調用此接口,可成功獲取用戶信息。
示例代碼
// 必須是在用戶已經受權的狀況下調用 wx.getUserInfo({ success(res) { const userInfo = res.userInfo const nickName = userInfo.nickName const avatarUrl = userInfo.avatarUrl const gender = userInfo.gender // 性別 0:未知、1:男、2:女 const province = userInfo.province const city = userInfo.city const country = userInfo.country } })
encryptedData 解密後爲如下 json 結構,詳見加密數據解密算法
{ "openId": "OPENID", "nickName": "NICKNAME", "gender": GENDER, "city": "CITY", "province": "PROVINCE", "country": "COUNTRY", "avatarUrl": "AVATARURL", "unionId": "UNIONID", "watermark": { "appid": "APPID", "timestamp": TIMESTAMP } }
示例代碼
<!-- 若是隻是展現用戶頭像暱稱,可使用 <open-data /> 組件 --> <open-data type="userAvatarUrl"></open-data> <open-data type="userNickName"></open-data> <!-- 須要使用 button 來受權登陸 --> <button wx:if="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo" > 受權登陸 </button> <view wx:else>請升級微信版本</view> Page({ data: { canIUse: wx.canIUse('button.open-type.getUserInfo') }, onLoad() { // 查看是否受權 wx.getSetting({ success(res) { if (res.authSetting['scope.userInfo']) { // 已經受權,能夠直接調用 getUserInfo 獲取頭像暱稱 wx.getUserInfo({ success(res) { console.log(res.userInfo) wx.request({ url: url, data: { 'iv': res.iv, 'encryptedData': res.encryptedData, 'login_key':登入標識 }, method: "POST", header: { 'content-type': 'application/json' // 默認值 }, success: function (res) { //解密後數據 console.log(res); } }); } }) } } }) }, bindGetUserInfo(e) { console.log(e.detail.userInfo) } })
叫你解密大法
小程序能夠經過各類前端接口獲取微信提供的開放數據。考慮到開發者服務器也須要獲取這些開放數據,微信會對這些數據作簽名和加密處理。開發者後臺拿到開放數據後能夠對數據進行校驗簽名和解密,來保證數據不被篡改。
簽名校驗以及數據加解密涉及用戶的會話密鑰 session_key。 開發者應該事先經過 wx.login 登陸流程獲取會話密鑰 session_key 並保存在服務器。爲了數據不被篡改,開發者不該該把 session_key 傳到小程序客戶端等服務器外的環境。
數據簽名校驗
爲了確保開放接口返回用戶數據的安全性,微信會對明文數據進行簽名。開發者能夠根據業務須要對數據包進行簽名校驗,確保數據的完整性。
如 wx.getUserInfo的數據校驗:
接口返回的rawData:
{ "nickName": "Band", "gender": 1, "language": "zh_CN", "city": "Guangzhou", "province": "Guangdong", "country": "CN", "avatarUrl": "http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0" }
用戶的 session-key:
HyVFkGl5F5OQWJZZaNzBBg==
用於簽名的字符串爲:
{"nickName":"Band","gender":1,"language":"zh_CN","city":"Guangzhou","province":"Guangdong","country":"CN","avatarUrl":"http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0"}HyVFkGl5F5OQWJZZaNzBBg==
使用sha1獲得的結果爲
75e81ceda165f4ffa64f4068af58c64b8f54b88c
加密數據解密算法
接口若是涉及敏感數據(如wx.getUserInfo
當中的 openId 和 unionId),接口的明文內容將不包含這些敏感數據。開發者如須要獲取敏感數據,須要對接口返回的加密數據(encryptedData) 進行對稱解密。 解密算法以下:
微信官方提供了多種編程語言的示例代碼(點擊下載)。每種語言類型的接口名字均一致。調用方式能夠參照示例。
另外,爲了應用能校驗數據的有效性,會在敏感數據加上數據水印( watermark )
watermark參數說明:
參數 | 類型 | 說明 |
---|---|---|
appid | String | 敏感數據歸屬 appId,開發者可校驗此參數與自身 appId 是否一致 |
timestamp | Int | 敏感數據獲取的時間戳, 開發者能夠用於數據時效性校驗 |
如接口 wx.getUserInfo
敏感數據當中的 watermark:
{ "openId": "OPENID", "nickName": "NICKNAME", "gender": GENDER, "city": "CITY", "province": "PROVINCE", "country": "COUNTRY", "avatarUrl": "AVATARURL", "unionId": "UNIONID", "watermark": { "appid": "APPID", "timestamp": TIMESTAMP } }
注:
會話密鑰 session_key 有效性
開發者若是遇到由於 session_key 不正確而校驗簽名失敗或解密失敗,請關注下面幾個與 session_key 有關的注意事項。