以上是登錄流程圖
說明:
- 調用 wx.login() 獲取 臨時登錄憑證code ,並回傳到開發者服務器。
- 調用 code2Session 接口,換取 用戶唯一標識 OpenID 和 會話密鑰 session_key。
- 調用 code2Session 接口拿到OpenID 去獲取token接口,根據openid 換取token
- 小程序請求登錄區內接口,通過wx.checkSession檢查登錄態,如果失效重新走上述登錄流程
- 根據需求:拿到token存儲在緩存中,並存儲遠程用戶信息
之后開發者服務器可以根據用戶標識來生成自定義登錄態,用於后續業務邏輯中前后端交互時識別用戶身份。
注意:
- 會話密鑰
session_key
是對用戶數據進行 加密簽名 的密鑰。為了應用自身的數據安全,開發者服務器不應該把會話密鑰下發到小程序,也不應該對外提供這個密鑰。 - 臨時登錄憑證 code 只能使用一次
代碼部分
wxutil.js 文件
/**
* Promise化小程序接口 JJ
*/
class WxUtil {
constructor() {
}
/**
* 初始化登陸
*/
initlogin() {
let {login, code2session, getToken, storeUserinfo} = this;
wx.checkSession({
success() {
//session_key 未過期,並且在本生命周期一直有效
let openid = wx.getStorageSync("openid")
if (openid) {
console.log("session_key未過期 本地有openind 重新獲取token");
getToken(openid).then(storeUserinfo).then(e => console.log(e)).catch(e => console.log(e));
} else {
console.log("本地無openid 重新獲取token");
login().then(code2session).then(getToken).then(storeUserinfo).then(r => console.log("token寫入本地", r)).catch(e => console.log(e));
}
},
fail() {
// session_key 已經失效,需要重新執行登錄流程
console.log("session_key過期 重新獲取token");
login().then(code2session).then(getToken).then(storeUserinfo).then(r => console.log("token寫入本地", r)).catch(e => console.log(e));
}
});
};
/**
* 登陸
*/
login() {
return new Promise((resolve, reject) => wx.login({success: resolve, fail: reject}));
};
/**
* 獲取openid server 有調用限制
*/
code2session(code) {
return new Promise((resolve, reject) =>
wx.request({
url: getApp().config.url + 'miniprogram/wxmp/code2session',
data: {
code: code.code
},
header: {
'content-type': 'application/json' // 默認值
},
success(res) {
if (res.statusCode === 200) {
var openid = res.data.data.openid;
if (openid) {
wx.setStorageSync("openid", res.data.data.openid);
resolve(res.data.data.openid)
}
}
reject(res.data);
}
}))
};
/**
* 根據openid 換取token
*/
getToken(openid) {
console.log("openid:" + openid);
return new Promise((resolve, reject) =>
wx.request({
url: getApp().config.url + 'auth/openid/token',
data: {
openid: openid
},
method: 'POST',
header: {
"Content-Type": "application/x-www-form-urlencoded",
'Authorization': 'Basic YXBwOmFwcA==' // 默認值
},
success(res) {
if (res.data.access_token) {
getApp().onFire.fire("loginSucess");
let tokenObj = res.data;
tokenObj.createTime = new Date().getTime()/1000;
wx.setStorageSync("tokenObj",tokenObj);
resolve(res.data);
} else {
reject(res.data);
}
}
}))
}
/**
* 刷新TOKEN todo
*/
refresToken() {
return new Promise((resolve, reject) => wx.getUserInfo({success: resolve, fail: reject}));
};
/**
* 存儲遠程用戶信息
*/
storeUserinfo(token) {
console.log("token", token)
return new Promise((resolve, reject) =>
wx.request({
url: getApp().config.url + 'admin/user/info',
data: {},
method: 'GET',
header: {
'content-type': 'application/json', // 默認值
'Authorization': `Bearer ${token.access_token}`
},
success(res) {
console.log("useinfo resdata.data");
wx.setStorageSync("userinfo", res.data.data);
}
}))
}
/**
* 獲取用戶信息
*/
getUserInfo() {
return new Promise((resolve, reject) => wx.getUserInfo({success: resolve, fail: reject}));
};
/**
* 檢測用戶狀態
*/
checkSession() {
return new Promise((resolve, reject) => wx.checkSession({success: resolve, fail: reject}));
};
}
export default WxUtil
app.js 文件
// 接口函數的調用
onShow (options) {
// token 過期情況p判斷
let {getToken,storeUserinfo} = this.wxutil;
let tokenObj = wx.getStorageSync("tokenObj");
let openid = wx.getStorageSync("openid");
if(tokenObj && openid){
let {createTime,expires_in} = tokenObj;
let isFetchToken = (createTime+expires_in) < (new Date().getTime()/1000 -1000)
if(isFetchToken){
getToken(openid).then(storeUserinfo).then(r=>console.log(r))
}
}
},
