1.前言
最近在学习小程序相关的开发内容,今天来梳理一下小程序的登录流程。然而在具体梳理登录流程前,可以谈谈微信小程序实现登录功能的意义所在:
- 用户身份识别:登录功能允许小程序识别和区分不同的用户,以提供个性化的服务和体验。通过登录,小程序可以获取用户的基本信息,如昵称、头像等,从而进行个性化展示、数据统计和用户行为分析。
- 数据关联和持久化:登录功能可以帮助小程序将用户的操作和数据与其身份进行关联和持久化。通过登录,小程序可以将用户的数据存储在服务器端,以便用户在不同设备上访问和同步数据。
- 权限控制:登录功能可以用于实现权限控制机制,确保只有授权用户才能访问特定的功能和资源。通过登录,小程序可以验证用户的身份和权限,限制某些功能或数据的访问范围。
针对小程序的登录功能实现,微信文档提供了一张时序图来进行说明,本文也基于该图来进行说明和补充,帮助大家对小程序的登录有一个初步的认识。
2.登录流程
2.1 自定义登录态
自定义登录态是指在用户登录后,为用户生成一个标识符,并将该标识符保存在后端服务器中,用于识别用户的身份和状态。这个标识符可以是一个字符串,比如用户的唯一标识或者一个随机生成的令牌。后端服务器在接收到请求时,可以通过检查该标识符来验证用户的登录状态和权限。
Token 也是一种用于身份验证和授权的标识符。在网络通信中,Token 通常是由服务器生成并返回给客户端,客户端在后续的请求中携带该 Token 来证明自己的身份和权限。Token 可以是一个包含用户信息和权限的加密字符串,也可以是一个随机生成的令牌。
自定义登录态和 Token 都可以用于实现用户的身份验证和授权,但具体实现方式可能有所不同。自定义登录态更注重于自定义的登录状态管理机制,而 Token 则更倾向于通用的身份验证和授权机制。在具体的应用场景中,可以根据需求选择适合的身份验证方案和标识符机制。
2.2 登录具体流程
一.小程序端
- 调用 wx.login 接口获取临时登录凭证 code:小程序调用 wx.login 接口,获取用户的临时登录凭证 code。
- 将 code 发送给服务器:小程序将获取到的 code 发送给后端服务器。
二 服务器端
- 服务器端请求微信服务器获取用户唯一标识和会话密钥:后端服务器使用小程序的 AppID 和 AppSecret,以及收到的 code,向微信服务器发起请求,获取用户的唯一标识 OpenID 和会话密钥 Session Key。
- 创建自定义登录态:后端服务器根据用户的 OpenID 和其他信息,生成一个自定义的登录态(如 Token 或自定义的登录标识符),并将其返回给小程序客户端。
三 小程序端
- 小程序端处理登录结果:小程序端根据后端服务器返回的登录结果,进行相应的处理。可以存储用户信息、更新登录状态等操作。
- 小程序端用户进行各种业务操作,小程序客户端在后续的请求中,将自定义登录态(Token 或登录标识符)携带到后端服务器,以验证用户的身份和权限。
四 服务器端
- 后端身份验证:后端服务器在接收到请求时,根据携带的登录态进行验证,确保用户的身份和权限有效。
- 身份验证成功后需要在数据库中保存用户的操作。
3.代码示例
简单模拟一下微信小程序获取code,以及生成token的流程
生成code的函数:
export function getLoginCode() {
return new Promise((resolve, reject) => {
wx.login({
timeout: 1000,
success: (res) => {
const code = res.code
resolve(code)
},
fail: err => {
console.log(err);
reject(err)
}
})
})
}
将code生成为token的后端请求:,(已经进行了request封装)
// 生成token
export function codeToToken(code) {
return diyLoginRequest.post("/login", {code})
}
详细的后端生成token代码:
exports.login = (req, res) => {
console.log("code:", req.body.code)
const queryString = `appid=${config.appId}&secret=${config.appSecret}&js_code=${req.body.code}&grant_type=authorization_code`;
const wxAPI = `https://api.weixin.qq.com/sns/jscode2session?${queryString}`;
axios.get(wxAPI)
.then(response =>{
console.log("-----", response.data);
if (response.data.errcode) {
return res.json(response.data)
}
User.findOne({openId: response.data.openid}, (err, user) => {
if(user) {
return res.json({
openid: response.data.openid,
token: generateToken({openid: response.data.openid})
})
} else {
const user = new User();
user.openId = response.data.openid;
user.save();
return res.json({
openid: response.data.openid,
token: generateToken({openid: response.data.openid})
})
}
})
})
.catch(error => {
console.log(error)
})
}
最终将模拟登录的流程编写在小程序的app.js当中,
loginAction: async function() {
// 1. 获取code
const code = await getLoginCode()
console.log('code', code);
// 2.将code发送给服务器
const result = await codeToToken(code)
const token = result.token
console.log('token:', token);
wx.setStorageSync(TOKEN_KEY, token)
},
如下图所示,就可以成功生成token。
此外补充一个函数来验证小程序的session是否过期
// 检查session是否过期
export function checkSession() {
return new Promise((resolve) => {
wx.checkSession({
success: () => {
resolve(true)
},
fail: () => {
resolve(false)
}
})
})
}