最近在开发微信小程序,发现小程序的登录流程和PC端略有差异,于是抽时间整理了一下登录流程。
首先,简单介绍下小程序登录的几个步骤。
1、点击登录按钮
2、获取微信sessionKey数据
1)调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
2)调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 和 会话密钥 session_key。
3、获取用户信息的加密数据(调用前需要 用户授权 scope.userInfo)
1)wx.getSetting() 获取用户的当前授权设置
2)wx.getUserInfo() 获取用户信息, object.success 回调函数的返回值如下:
4、调用后端登录接口,绑定用户。
wx.getSetting() 调用成功返回结果如下:
属性 | 类型 | 说明 |
---|---|---|
authSetting | AuthSetting | 用户授权结果 |
subscriptionsSetting | SubscriptionsSetting | 用户订阅消息设置,接口参数withSubscriptions 值为true 时才会返回。 |
wx.getUserInfo() 调用成功返回结果如下:
属性 | 类型 | 说明 |
---|---|---|
userInfo | UserInfo | 用户信息对象,不包含 openid 等敏感信息 |
rawData | string | 不包括敏感信息的原始数据字符串,用于计算签名 |
signature | string | 使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息,详见 用户数据的签名验证和加解密 |
encryptedData | string | 包括敏感数据在内的完整用户信息的加密数据,详见 用户数据的签名验证和加解密 |
iv | string | 加密算法的初始向量,详见 用户数据的签名验证和加解密 |
cloudID | string | 敏感数据对应的云 ID,开通云开发的小程序才会返回,可通过云调用直接获取开放数据,详细见云调用直接获取开放数据 |
整个登录流程的js代码如下:
loginClick() {
if (this.userName == "" || this.password == "") {
WechatUtil.showToast("请输用户名密码");
return;
}
wx.showLoading({
title: "正在登录中..." });
this.login(this.userName, this.password);
wx.hideLoading();
},
async login() {
// 1、获取微信sessionKey数据
let res = await this.getWxSessionByCode();
if (res.code !== 0) {
wx.showToast({
title: res.message, icon: "none" });
return false;
}
let wxSessionInfoVO = res.value;
let sessionKey = wxSessionInfoVO.sessionKey;
let openId = wxSessionInfoVO.openId;
// 2、获取用户信息的加密数据
let getUserInfoRes = await this.getUserInfoFromWx();
let userInfo = getUserInfoRes.userInfo;
if (!userInfo) {
WechatUtil.showToast("获取用户信息失败");
return false;
}
//3、绑定用户,调用后端登录接口
let accountByEncryData = {
appId: this.$store.state.appId, //小程序appId
loginName: this.userName, //用户名
password: this.password, //密码
sessionKey: sessionKey,
encryptedData: getUserInfoRes.encryptedData, //wx.getUserInfo的返回值 加密数据
iv: getUserInfoRes.iv //wx.getUserInfo的返回值 加密算法的初始向量
};
let successd = await this.loginByAccountAndEncryData(accountByEncryData);
return successd;
}
根据getWxCode返回的code,调用后端接口获取openid和session_key
// 获取微信sessionKey和openId
async getWxSessionByCode() {
const wxCodeRes = await this.getWxCode();
const params = {
code: wxCodeRes.code,
appId: this.$store.state.appId
};
const res = await loginService.getWxSessionByCode(params);
return res;
}
接口返回的数据结构如下:
{
code: 0,
message: "操作成功"
value: {
openId: "obXSv4rgXCppd1MBHFXDyNAhZz7k"
sessionKey: "4ti+o+fgFITR2DnpcHAIgg=="
unionId: null
}
}
调用微信接口获取登录凭证(code),通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)等
// 获取登录凭证code 有效期5分钟,且只能使用一次
getWxCode() {
return new Promise((resolve, reject) => {
let reqObj = {
success: res => {
resolve(res);
},
fail: res => {
reject(res);
}
};
wx.login(reqObj);
});
}
包含加密数据UnionId,需要提前进行用户授权 、并且调过wx.login接口
async getUserInfoFromWx() {
try {
// 获取用户是否授权微信 获取用户信息
let settingRes = await this.getAuthorizeSetting();
if (!settingRes.authSetting["scope.userInfo"]) {
WechatUtil.showToast("授权失败");
return null;
}
return new Promise((resolve, reject) => {
let getUserInfoOpt = {
withCredentials: true,
success: res => {
resolve(res);
},
fail: res => {
reject(res);
}
};
// 必须是在用户已经授权的情况下调用
wx.getUserInfo(getUserInfoOpt);
});
} catch (e) {
WechatUtil.showToast("微信服务器异常");
}
}
wx.getUserInfo官网介绍
获取用户的授权设置。返回值中只会出现小程序已经向用户请求过的权限。
// 获取用户是否授权微信 获取用户信息
getAuthorizeSetting() {
return new Promise((resolve, reject) => {
let reqObj = {
success: res => {
resolve(res);
},
fail: res => {
reject(res);
}
};
wx.getSetting(reqObj);
});
}
wx.getSetting官网介绍
async loginByAccountAndEncryData(params) {
let res = await loginService.loginByAccountAndEncryData(params);
if (res.code != 0) {
WechatUtil.showToast(res.message, 1000);
return false;
}
this.$store.state.userId = res.value;
this.$store.state.logouted = false;
wx.setStorageSync("userId", res.value);
wx.reLaunch({
url: "/pages/home/main" }); //登录成功跳转首页
},