输入用户名和密码,返回token。这个token最好存储在redis中,设置过期时间2小时,过期后就不能使用。或者存储在数据库中。
只要是没有过期的token都可以作为调用接口的凭证。所以多个用户登录就有多个token返回。
调用接口的方式:
将token放在header中。
比如:
// 以微信小程序 wx.request 为例[citation:5]
wx.request({
url: 'https://api.example.com/data',
method: 'POST',
header: { // 此处设置请求头参数
'Content-Type': 'application/json', // 告诉服务器发送的是JSON数据
'Authorization': 'Bearer your_token_here', // 传递身份令牌
'X-Custom-Header': 'CustomValue' // 传递任何自定义业务参数
},
data: { // 请求体数据,与header是独立的
key1: 'value1',
key2: 'value2'
},
success(res) {
console.log(res.data);
}
})
接口接收token:
const express = require('express');
const app = express();
const PORT = 3000;
// 中间件:解析JSON请求体
app.use(express.json());
// 模拟用户数据库(实际项目中应使用数据库)
const mockUsers = [
{ id: 1, username: 'user1', role: 'admin' },
{ id: 2, username: 'user2', role: 'user' }
];
// 模拟令牌存储(实际项目中应使用Redis等)
const validTokens = new Map();
// 生成模拟令牌(实际项目中应使用JWT等)
function generateToken(userId) {
const token = `token_${userId}_${Date.now()}`;
validTokens.set(token, {
userId,
expiresAt: Date.now() + 3600000 // 1小时后过期
});
return token;
}
// 中间件:验证Bearer Token
function verifyToken(req, res, next) {
// 1. 从Authorization头获取令牌
const authHeader = req.headers['authorization'];
if (!authHeader) {
return res.status(401).json({
code: 401,
message: '未提供认证令牌',
error: 'Missing Authorization header'
});
}
// 2. 检查是否为Bearer Token
const parts = authHeader.split(' ');
if (parts.length !== 2 || parts[0] !== 'Bearer') {
return res.status(401).json({
code: 401,
message: '令牌格式错误,应为 "Bearer <token>"',
error: 'Invalid token format'
});
}
const token = parts[1];
// 3. 验证令牌有效性
const tokenData = validTokens.get(token);
if (!tokenData) {
return res.status(401).json({
code: 401,
message: '令牌无效或已过期',
error: 'Invalid token'
});
}
// 4. 检查令牌是否过期
if (Date.now() > tokenData.expiresAt) {
validTokens.delete(token); // 清理过期令牌
return res.status(401).json({
code: 401,
message: '令牌已过期',
error: 'Token expired'
});
}
// 5. 查找对应用户信息
const user = mockUsers.find(u => u.id === tokenData.userId);
if (!user) {
return res.status(401).json({
code: 401,
message: '用户不存在',
error: 'User not found'
});
}
// 6. 将用户信息附加到请求对象,供后续中间件/路由使用
req.user = user;
req.token = token;
// 令牌验证通过,继续下一个中间件/路由
next();
}
// ==================== 接口路由 ====================
// 1. 登录接口(获取Token)
app.post('/api/auth/login', (req, res) => {
const { username, password } = req.body;
// 模拟用户验证(实际项目中应验证密码哈希)
const user = mockUsers.find(u => u.username === username);
if (!user) {
return res.status(401).json({
code: 401,
message: '用户名或密码错误',
error: 'Invalid credentials'
});
}
// 生成令牌
const token = generateToken(user.id);
res.json({
code: 200,
message: '登录成功',
data: {
token,
user: {
id: user.id,
username: user.username,
role: user.role
},
expiresIn: 3600 // 令牌有效时间(秒)
}
});
});
// 2. 需要Token验证的受保护接口
app.get('/api/user/profile', verifyToken, (req, res) => {
// 通过verifyToken中间件后,req.user已包含用户信息
res.json({
code: 200,
message: '获取用户信息成功',
data: {
user: req.user,
timestamp: new Date().toISOString()
}
});
});
// 3. 需要Token验证的POST接口(接收小程序请求)
app.post('/api/data/submit', verifyToken, (req, res) => {
const requestBody = req.body;
const customHeader = req.headers['x-custom-header'];
res.json({
code: 200,
message: '数据接收成功',
data: {
receivedData: requestBody,
customHeader: customHeader,
processedBy: req.user.username,
serverTime: new Date().toISOString()
}
});
});
// 4. 令牌刷新接口
app.post('/api/auth/refresh', verifyToken, (req, res) => {
const oldToken = req.token;
const newToken = generateToken(req.user.id);
// 使旧令牌失效
validTokens.delete(oldToken);
res.json({
code: 200,
message: '令牌刷新成功',
data: {
token: newToken,
expiresIn: 3600
}
});
});
// 5. 登出接口
app.post('/api/auth/logout', verifyToken, (req, res) => {
validTokens.delete(req.token);
res.json({
code: 200,
message: '登出成功'
});
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error('服务器错误:', err);
res.status(500).json({
code: 500,
message: '服务器内部错误',
error: process.env.NODE_ENV === 'development' ? err.message : undefined
});
});
// 启动服务器
app.listen(PORT, () => {
console.log(`✅ 服务器已