[阶段1.1-1.7] 实现完整的认证系统
后端实现: - 创建 AuthService 包含密码加密、JWT 生成和验证 - 创建 authMiddleware 用于 API 路由保护 - 实现 auth 路由 (register, login, logout, /me) 前端实现: - 创建 Login 页面 (登录/注册标签页) - 创建 ProtectedRoute 组件用于路由保护 - 更新 App.tsx 集成路由保护 - 前端 API 客户端已包含认证方法和拦截器 验收标准已满足: - 用户可以注册和登录 - JWT Token 正确生成和验证 - 受保护的路由需要有效 Token - 未认证用户重定向到登录页面 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
65
server/src/middleware/authMiddleware.ts
Normal file
65
server/src/middleware/authMiddleware.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { verifyToken } from '../services/AuthService';
|
||||
import { AppError } from './errorHandler';
|
||||
|
||||
export interface AuthRequest extends Request {
|
||||
userId?: string;
|
||||
userEmail?: string;
|
||||
}
|
||||
|
||||
export function authMiddleware(req: AuthRequest, res: Response, next: NextFunction) {
|
||||
const authHeader = req.headers.authorization;
|
||||
|
||||
if (!authHeader) {
|
||||
return res.status(401).json({
|
||||
error: {
|
||||
status: 401,
|
||||
message: 'Missing authorization header',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const parts = authHeader.split(' ');
|
||||
if (parts.length !== 2 || parts[0] !== 'Bearer') {
|
||||
return res.status(401).json({
|
||||
error: {
|
||||
status: 401,
|
||||
message: 'Invalid authorization header format',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const token = parts[1];
|
||||
|
||||
try {
|
||||
const payload = verifyToken(token);
|
||||
req.userId = payload.userId;
|
||||
next();
|
||||
} catch (error: any) {
|
||||
return res.status(401).json({
|
||||
error: {
|
||||
status: 401,
|
||||
message: 'Invalid or expired token',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function optionalAuthMiddleware(req: AuthRequest, res: Response, next: NextFunction) {
|
||||
const authHeader = req.headers.authorization;
|
||||
|
||||
if (authHeader) {
|
||||
const parts = authHeader.split(' ');
|
||||
if (parts.length === 2 && parts[0] === 'Bearer') {
|
||||
const token = parts[1];
|
||||
try {
|
||||
const payload = verifyToken(token);
|
||||
req.userId = payload.userId;
|
||||
} catch (error) {
|
||||
// Silently fail - continue without authentication
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
Reference in New Issue
Block a user