1. 前言
- 登录很简单,基本都做过,但是进行总结的可能不多
- 今天闲来无事就总结一波
2. 登录方式
- 微信小程序的登录流程分为两种情况
- 一种是使用微信开放平台登录
- 一种是使用自定义登录方式
3. 使用微信开放平台登录
- 用户在小程序中点击
登录按钮,触发登录事件。- 小程序调用
wx.login()方法获取临时登录凭证code。- 小程序调用
wx.getUserInfo()方法获取用户的基本信息(头像、昵称等)。- 小程序将
code和用户信息发送给开发者的后台服务器。- 开发者的后台服务器使用
AppID和AppSecret调用微信接口获取 session_key 和 openid。- 开发者的后台服务器使用
session_key对用户信息进行解密,获取用户的真实信息。- 开发者的后台服务器将用户的信息存储到数据库中,并生成一个自定义登录态
token并返回给小程序。- 小程序
保存该自定义登录态token,并在以后的请求中带上该token。
4. 相关代码
- 客户端授权登录
// 点击按钮触发登录事件
wx.login({
success: res => {
// 获取临时登录凭证
const code = res.code;
// 获取用户信息
wx.getUserInfo({
success: res => {
const userInfo = res.userInfo;
// 将 code 和 userInfo 发送给后台服务器
wx.request({
url: 'https://xx.xx.com/api/login',
data: {
code: code,
userInfo: userInfo
},
success: res => {
// 将服务器返回的自定义登录态 token 存储到本地
wx.setStorageSync('token', res.data.token);
}
});
}
});
}
});
- 后台服务器处理登录逻辑
const request = require('request');
const crypto = require('crypto');
const APP_ID = '你的 app id';
const APP_SECRET = '你的 app secret';
// 处理小程序端登录请求
function login(req, res) {
const code = req.body.code;
const userInfo = req.body.userInfo;
// 获取 session_key 和 openid
request(`https://api.weixin.qq.com/sns/jscode2session?appid=${APP_ID}&secret=${APP_SECRET}&js_code=${code}&grant_type=authorization_code`, function(error, response, body) {
const result = JSON.parse(body);
const session_key = result.session_key;
const openid = result.openid;
// 使用 session_key 对用户信息进行解密
const encryptedData = userInfo.encryptedData;
const iv = userInfo.iv;
const decipher = crypto.createDecipheriv('aes-128-cbc', new Buffer(session_key, 'base64'), new Buffer(iv, 'base64'));
let decoded = decipher.update(encryptedData, 'base64', 'utf8');
decoded += decipher.final('utf8');
const userInfoObj = JSON.parse(decoded);
// 将用户信息存储到数据库中,生成自定义登录态 token 并返回
const token = generateToken(userInfoObj);
res.json({ token: token });
});
}
// 生成自定义登录态 token
function generateToken(userInfo) {
const secret = 'your secret key';
const expireTime = new Date().getTime() + 24 * 3600 * 1000;
const data = JSON.stringify({
userInfo: userInfo,
expireTime: expireTime
});
const hash = crypto.createHmac('sha256', secret).update(data).digest('hex');
const token = `${data}.${hash}`;
return token;
}
只是大概流程 没有考虑用户退出登录、token 过期等其他情况的处理。
5. 自定义登录方式
- 用户在小程序中输入
账号密码,点击“登录”按钮,触发登录事件。- 小程序将用户输入的账号密码
发送给开发者的后台服务器。- 开发者的
后台服务器根据账号密码验证用户的身份,并生成一个自定义登录态token并返回给小程序。- 小程序保存该自定义登录态 token,并在以后的
请求中带上该token。
- 需要注意的是,在使用自定义登录方式时,为了保障用户数据的安全,需要使用 HTTPS 协议,并对用户密码进行加密传输和存储
6. 相关代码
- 客户端登录逻辑
// 自定义登录函数,使用用户名和密码登录
const login = (username, password) => {
return new Promise((resolve, reject) => {
wx.request({
url: 'https://xx.yzs.com/api/login',
method: 'POST',
data: {
username: username,
password: password
},
success: res => {
// 将服务器返回的自定义登录态 token 存储到本地
wx.setStorageSync('token', res.data.token);
resolve(res.data);
},
fail: err => {
reject(err);
}
});
});
};
// 在登录页面中调用 login 函数进行登录
const handleLogin = () => {
const username = '密码';
const password = '用户名';
login(username, password).then(res => {
// 登录成功,跳转到首页
wx.redirectTo({
url: '/pages/home/index',
});
}).catch(err => {
// 登录失败,提示错误信息
wx.showToast({
title: '登录失败,请重试!',
icon: 'none'
});
});
};
- 后台相关逻辑
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const crypto = require('crypto');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// 处理自定义登录请求
app.post('/api/login', (req, res) => {
const username = req.body.username;
const password = req.body.password;
// 根据用户名和密码查询用户信息
const user = getUserByUsernameAndPassword(username, password);
if (!user) {
res.status(401).json({ message: '用户名或密码错误!' });
return;
}
// 将用户信息存储到数据库中,生成自定义登录态 token 并返回
const token = generateToken(user);
res.json({ token: token });
});
// 生成自定义登录态 token
const generateToken = user => {
const secret = '自己的secret key';
const expireTime = new Date().getTime() + 24 * 3600 * 1000;
const data = JSON.stringify({
userId: user.id,
expireTime: expireTime
});
const hash = crypto.createHmac('sha256', secret).update(data).digest('hex');
const token = `${data}.${hash}`;
return token;
};
// 根据用户名和密码查询用户信息
const getUserByUsernameAndPassword = (username, password) => {
// TODO: 实现根据用户名和密码查询用户信息的逻辑
return {
id: 123,
username: 'testuser',
nickname: 'Test User'
};
};
app.listen(3000, () => {
console.log('Server started on port 3000.');
});
7. 请求配置 token
- 核心代码
// 假设 token 存在于本地缓存中,缓存的键名为 'token'
const token = wx.getStorageSync('token')
wx.request({
url: 'https://xx.com/api/some-resource',
header: {
'Authorization': `Bearer ${token}`
},
success(res) {
console.log(res.data)
},
fail(err) {
console.error(err)
}
})
- 通过
wx.getStorageSync()方法获取本地缓存中存储的 token,- 然后将其添加到
header对象中的 Authorization 属性中,值为 Bearer ${token},- 其中 Bearer 为固定字符串,
${token}是变量,表示真正的 token 值。- 最终发送的请求头会包含
Authorization: Bearer ${token},其中 ${token} 会被替换为真实的 token 值。












网友评论