#小程序的登錄和受權

1.小程序登陸

登入官方說明html

小程序能夠經過微信官方提供的登陸能力方便地獲取微信提供的用戶身份標識,快速創建小程序內的用戶體系。前端

登陸流程時序算法

說明:編程

  1. 調用 wx.login() 獲取 臨時登陸憑證code ,並回傳到開發者服務器。
  2. 調用 code2Session 接口,換取 用戶惟一標識 OpenID會話密鑰 session_key

以後開發者服務器能夠根據用戶標識來生成自定義登陸態,用於後續業務邏輯中先後端交互時識別用戶身份。json

注意:小程序

  1. 會話密鑰 session_key 是對用戶數據進行 加密簽名 的密鑰。爲了應用自身的數據安全,開發者服務器不該該把會話密鑰下發到小程序,也不該該對外提供這個密鑰
  2. 臨時登陸憑證 code 只能使用一次

兄弟們,是否是很簡單,一看就會?我知道大家的回答以下圖,可是不要慌,咱們詳細講每一步後端

小程序端執行wx.login後在回調函數中就能拿到上圖的code,而後把這個code傳給咱們後端程序,後端拿到這個這個code後,能夠請求code2Session接口拿到用的openid和session_key,openid是用戶在微信中惟一標識,咱們就能夠把這個兩個值(val)存起來,而後返回一個鍵(key)給小程序端,下次小程序請求咱們後端的時候,帶上這個key,咱們就能找到這個val,就能夠,這樣就把登入作好了。api

1.1wx.login(Object object)

調用接口獲取登陸憑證(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)
    }
  }
})

1.2code2Session

本接口應在服務器端調用,詳細說明參見服務端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?這個就是在用戶受權的時候用的,用來解密用戶的數據,還要解密?是的你沒有聽錯,不要慌,下面給你解釋

2.微信受權獲取用戶信

後端獲取微信用戶信息流程

微信官方:忘了告訴你,session_key還會過時的,是的,沒錯就是這樣坑爹。

個人回覆:我就是頭鐵,我無論session_key過時,會帶來什麼樣的後果呢?

微信官方:對不起,你頭鐵沒有,你後端程序沒法用戶受權的數據,就問你氣不氣?

個人回覆:好的,你牛逼,我能夠接收你session_key過時,可是你要告訴我怎麼判斷他是過時的吧?怎麼獲取新的session_key吧?

微信官方:仍是要按照個人要求來吧?看你這麼可憐,告訴你吧,用wx.checkSession判斷是否過時,若是過時就重寫登入吧!獲取新的code,後端在去請求code2Session獲取新的session_key

個人回覆:好的,謝謝你sb

判斷session_key有沒有過時

2.1wx.checkSession(Object object)

檢查登陸態是否過時。

經過 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接口獲取數據了**

個人回覆:媽的,怎麼這麼麻煩?

微信官方:對不起,大佬,沒有辦法啊,咱們要保護用戶的信息安全啊

個人回覆:哦

2.2wx.getSetting(Object object)

基礎庫 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
    // }
  }
})

注意事項

  1. wx.authorize({scope: "scope.userInfo"}),不會彈出受權窗口,請使用 <button_open-type="getUserInfo">
  2. 須要受權 scope.userLocation 時必須配置地理位置用途說明

微信官方:當你小程序端調用咱們wx.getUserInfo的時候,咱們會返回你用的基本信息。

個人回覆:什麼是基本信息,哪些是敏感信息?我後端怎麼獲取呢?

微信官方:好比openid這些,大佬,你又兩種方法,第一:你能夠將這些基本信息傳到後端,第二: 你能夠講getUserInfo中的 iv,encryptedData傳給後端解密,機密後就能獲取到用戶的敏感信息了

個人回覆:好的,我後端怎麼解密呢?用什麼解密呢?

微信官方:你登入的時候不是,後端不是存了session_key嗎?加上這些數據,就能夠解密了

個人回覆:哦

2.3wx.getUserInfo(Object object)

獲取用戶信息

調用前須要 用戶受權 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)
  }
})

叫你解密大法

2.4開放數據校驗與解密

小程序能夠經過各類前端接口獲取微信提供的開放數據。考慮到開發者服務器也須要獲取這些開放數據,微信會對這些數據作簽名和加密處理。開發者後臺拿到開放數據後能夠對數據進行校驗簽名和解密,來保證數據不被篡改。

img

簽名校驗以及數據加解密涉及用戶的會話密鑰 session_key。 開發者應該事先經過 wx.login 登陸流程獲取會話密鑰 session_key 並保存在服務器。爲了數據不被篡改,開發者不該該把 session_key 傳到小程序客戶端等服務器外的環境。

數據簽名校驗

爲了確保開放接口返回用戶數據的安全性,微信會對明文數據進行簽名。開發者能夠根據業務須要對數據包進行簽名校驗,確保數據的完整性。

  1. 經過調用接口(如 wx.getUserInfo)獲取數據時,接口會同時返回 rawData、signature,其中 signature = sha1( rawData + session_key )
  2. 開發者將 signature、rawData 發送到開發者服務器進行校驗。服務器利用用戶對應的 session_key 使用相同的算法計算出簽名 signature2 ,比對 signature 與 signature2 便可校驗數據的完整性。

如 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) 進行對稱解密。 解密算法以下:

  1. 對稱解密使用的算法爲 AES-128-CBC,數據採用PKCS#7填充。
  2. 對稱解密的目標密文爲 Base64_Decode(encryptedData)。
  3. 對稱解密祕鑰 aeskey = Base64_Decode(session_key), aeskey 是16字節。
  4. 對稱解密算法初始向量 爲Base64_Decode(iv),其中iv由數據接口返回。

微信官方提供了多種編程語言的示例代碼(點擊下載)。每種語言類型的接口名字均一致。調用方式能夠參照示例。

另外,爲了應用能校驗數據的有效性,會在敏感數據加上數據水印( 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
  }
}

注:

  1. 解密後獲得的json數據根據需求可能會增長新的字段,舊字段不會改變和刪減,開發者須要預留足夠的空間

會話密鑰 session_key 有效性

開發者若是遇到由於 session_key 不正確而校驗簽名失敗或解密失敗,請關注下面幾個與 session_key 有關的注意事項。

  1. wx.login 調用時,用戶的 session_key 可能會被更新而導致舊 session_key 失效(刷新機制存在最短週期,若是同一個用戶短期內屢次調用 wx.login,並不是每次調用都致使 session_key 刷新)。開發者應該在明確須要從新登陸時才調用 wx.login,及時經過 code2Session 接口更新服務器存儲的 session_key。
  2. 微信不會把 session_key 的有效期告知開發者。咱們會根據用戶使用小程序的行爲對 session_key 進行續期。用戶越頻繁使用小程序,session_key 有效期越長。
  3. 開發者在 session_key 失效時,能夠經過從新執行登陸流程獲取有效的 session_key。使用接口 wx.checkSession能夠校驗 session_key 是否有效,從而避免小程序反覆執行登陸流程。
  4. 當開發者在實現自定義登陸態時,能夠考慮以 session_key 有效期做爲自身登陸態有效期,也能夠實現自定義的時效性策略。
相關文章
相關標籤/搜索