feat: 实现Token刷新机制,缩短登录有效期
安全改进: - Access Token有效期从7天缩短为2小时 - 添加Refresh Token机制(有效期7天) - 关闭浏览器后较快失效,提升安全性 后端修改(auth.js): - 添加generateRefreshToken函数生成刷新令牌 - 添加refreshAccessToken函数验证并刷新access token - 分离ACCESS_TOKEN_EXPIRES和REFRESH_TOKEN_EXPIRES配置 后端修改(server.js): - 登录时返回refreshToken和expiresIn - 添加/api/refresh-token接口用于刷新token - Cookie有效期同步调整为2小时 前端修改(app.js): - 保存refreshToken到localStorage - 添加自动刷新定时器(过期前5分钟刷新) - 页面加载时若token过期自动尝试刷新 - 登出时清除refreshToken和定时器 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,7 @@ const execAsync = util.promisify(exec);
|
||||
const execFileAsync = util.promisify(execFile);
|
||||
|
||||
const { db, UserDB, ShareDB, SettingsDB, VerificationDB, PasswordResetTokenDB, SystemLogDB } = require('./database');
|
||||
const { generateToken, authMiddleware, adminMiddleware, isJwtSecretSecure } = require('./auth');
|
||||
const { generateToken, generateRefreshToken, refreshAccessToken, authMiddleware, adminMiddleware, isJwtSecretSecure } = require('./auth');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 40001;
|
||||
@@ -1632,6 +1632,7 @@ app.post('/api/login',
|
||||
}
|
||||
|
||||
const token = generateToken(user);
|
||||
const refreshToken = generateRefreshToken(user);
|
||||
|
||||
// 清除失败记录
|
||||
if (req.rateLimitKeys) {
|
||||
@@ -1648,7 +1649,7 @@ app.post('/api/login',
|
||||
secure: isSecureEnv,
|
||||
// HTTPS环境使用strict,HTTP环境使用lax(开发环境兼容)
|
||||
sameSite: isSecureEnv ? 'strict' : 'lax',
|
||||
maxAge: 7 * 24 * 60 * 60 * 1000, // 7天
|
||||
maxAge: 2 * 60 * 60 * 1000, // 2小时(与access token有效期一致)
|
||||
path: '/' // 限制Cookie作用域
|
||||
});
|
||||
|
||||
@@ -1659,6 +1660,8 @@ app.post('/api/login',
|
||||
success: true,
|
||||
message: '登录成功',
|
||||
token,
|
||||
refreshToken, // 返回refresh token
|
||||
expiresIn: 2 * 60 * 60 * 1000, // 告知前端access token有效期(毫秒)
|
||||
user: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
@@ -1683,6 +1686,43 @@ app.post('/api/login',
|
||||
}
|
||||
);
|
||||
|
||||
// 刷新Access Token
|
||||
app.post('/api/refresh-token', (req, res) => {
|
||||
const { refreshToken } = req.body;
|
||||
|
||||
if (!refreshToken) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '缺少刷新令牌'
|
||||
});
|
||||
}
|
||||
|
||||
const result = refreshAccessToken(refreshToken);
|
||||
|
||||
if (!result.success) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
message: result.message
|
||||
});
|
||||
}
|
||||
|
||||
// 更新Cookie中的token
|
||||
const isSecureEnv = process.env.COOKIE_SECURE === 'true';
|
||||
res.cookie('token', result.token, {
|
||||
httpOnly: true,
|
||||
secure: isSecureEnv,
|
||||
sameSite: isSecureEnv ? 'strict' : 'lax',
|
||||
maxAge: 2 * 60 * 60 * 1000, // 2小时
|
||||
path: '/'
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
token: result.token,
|
||||
expiresIn: 2 * 60 * 60 * 1000
|
||||
});
|
||||
});
|
||||
|
||||
// ===== 需要认证的API =====
|
||||
|
||||
// 获取当前用户信息
|
||||
|
||||
Reference in New Issue
Block a user