登錄流程
1. 三個角色:
- 小程序端
- 微信自己的服務器
- 公司的服務器
2. openid
openid:每一個微信用戶的唯一標識
openid一般不保存在客戶端,一般保存在服務器端。
我們自己的服務器會和微信的服務器進行通信。到時候微信的服務器就會返回一個session_key和openid,到時候我們的服務器會把這個openid存到數據庫中。
3. 登錄的過程:
- 我們的小程序端先調用接口 wx.login(),向微信的服務器發送請求,獲取到一個code,這個code在我們的客戶端是沒有用的。
1.1 這個code的作用是發送到我們自己的服務器
1.2 微信小程序端通過調用wx.request()將code發送到我們的服務器
1.3 服務器拿到code和appid(一開始申請到的)和appsecret
1.4 appsecret是怎麼獲取的:在小程序控制臺,和appid在一個地方,可以重置。 - 我們的服務器與微信的服務器進行一次溝通,將code+appid+appsecret這三個東西傳遞給微信的服務器,
- 微信的服務器會返回session_key和openid。服務器就拿到了openid,不會傳給客戶端,而是將openid存到服務器。
3.1 有時候,公司希望不僅能用微信登錄,還可以用用戶名+密碼登錄小程序。
3.2 一般用賬號+密碼登錄的時候,會在第一步,先讓用戶輸入用戶和密碼,服務器驗證通過以後,再將賬號+密碼+code發送給微信的服務器,換取openid;之後將openid+賬號+密碼存儲在數據庫的某個表中(t_user)。 - 服務器端驗證通過之後,會向客戶端返回一個token,登錄狀態。客戶端會把token保存起來。小程序中有個storage,一般將token保存在storage中。
- 下次再打開小程序的時候,就可以先從緩存中拿出token來,發送給服務器,驗證一下是否過期,不用每次打開都登錄一下了。如果過期了再登錄,沒過期的話就直接使用這個。
- 以後客戶端向服務器發送請求(請求需要在登錄的狀態下才會返回結果時),會攜帶token。服務器會根據token查詢openid或者session_key和其他數據。然後將數據返回給客戶端。
4. 簡化後的流程:
- 調用wx.login獲取code
- 調用wx.request發送code到我們自己的服務器(我們自己的服務器會返回一個登錄狀態的標識,比如token)
- 將登錄狀態的標識token進行存儲,以便下次使用
- 請求需要登錄狀態的接口時,帶上這個token。
5. 官方圖解
官方文檔:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
代碼演練
接口:
- 登錄接口
- token是否過期的接口
登錄接口:
接口:/login
method:post
參數:code (如果想要賬號和密碼登錄的話,傳遞code+賬號+密碼)
返回:token
token是否過期的接口:
接口:/auth
method:post
參數:header,token,將token放在header中傳遞過去
返回值:
錯誤碼:
1001:沒有傳入token
1002:傳入錯誤的token
1003:token過期。
一般情況下,登錄在app.js中做,不用等到進入某個頁面再做。
wx.setStorage與wx.setStorageSync的區別:
- wx.setStorage是異步的
- wx.setStorageSync是同步的
小程序登錄的流程代碼大體如下:
// 註冊小程序的示例
const TOKEN = "token"; // 規範寫法,寫成常量,也可以抽取出來到一個常量文件中。
App({
// 全局對象,一旦小程序關閉掉,會被回收
globalData: {
token: "", //token
},
// 小程序初始化完成時,加載完,一般在這裏進行登錄操作
onLaunch: function(options) {
// 3. 做登錄操作
// 3.1 先在緩存中取出token,如果有,就驗證;沒有再登錄。
const token = wx.getStorageSync(TOKEN);
// 3.2 判斷token是否有值,並且判斷長度>0
if (token && token.length > 0) { // 已經有token,需要驗證是否過期
console.log("執行了驗證token操作");
// 驗證token是否過期
this.checkToken(token);
} else { // 還沒有token,所以得先登錄
this.login(); // 登錄一下
}
},
// 登錄的代碼
login() {
console.log("執行了登錄操作");
wx.login({
success: (res) => {
console.log(res.code); // code只有5分鐘的有效期
// 1. 獲取code
const code = res.code;
// 2. 將code發送給自己的服務器
wx.request({
url: 'http://123.207.32.32:3000/login', // 調用了別人的接口
method: "post",
data: {
code,
},
success: (res) => {
console.log(res); // 服務器會返回一個token
// token的作用:在首頁,關於啥的頁面,都攜帶token才能查看某些內容
// 拿到token,很多地方都要用,所以最好保存到全局中。
// 3. 保存到全局
const token = res.data.token;
this.globalData.token = token; // 爲了this有效,要都寫成箭頭函數的形式
console.log(this.globalData.token);
// 4. token進行本地存儲(同步的)
wx.setStorageSync(TOKEN, token);
},
fail: function(error) {
console.log(error);
}
})
}
})
},
// 驗證token是否過期
checkToken(token){
wx.request({
url: 'http://123.207.32.32:3000/auth',
method: "post",
header: {
token,
},
success: (res) => {
if(!res.data.errCode){ // token有效
this.globalData.token = token;
}else{ // token無效,得重新登錄
this.login();
}
},
fail: (error) => {
console.log(error);
}
})
}
})