Spaces:
Sleeping
Sleeping
| import { type Request, type Response, type NextFunction } from 'express'; | |
| import db from '../lib/db.js'; | |
| export interface AuthenticatedRequest extends Request { | |
| user: { | |
| userId: string; | |
| apiKeyId: string; | |
| }; | |
| } | |
| /** | |
| * 验证外部 API Key (Bearer Token 格式) | |
| * 支持 Header: Authorization: Bearer sk_... | |
| */ | |
| export const verifyApiKey = (req: Request, res: Response, next: NextFunction) => { | |
| const authHeader = req.headers.authorization; | |
| if (!authHeader || !authHeader.startsWith('Bearer ')) { | |
| return res.status(401).json({ | |
| error: { | |
| message: "Missing or invalid API key. Please provide your key in 'Authorization: Bearer sk_...' header.", | |
| type: "invalid_request_error", | |
| code: "api_key_missing" | |
| } | |
| }); | |
| } | |
| const apiKey = authHeader.split(' ')[1]; | |
| try { | |
| const keyRecord = db.prepare('SELECT id, user_id, last_used, status FROM api_keys WHERE key_secret = ?').get(apiKey) as any; | |
| if (!keyRecord) { | |
| return res.status(401).json({ | |
| error: { | |
| message: "Incorrect API key provided.", | |
| type: "authentication_error", | |
| code: "invalid_api_key" | |
| } | |
| }); | |
| } | |
| if (keyRecord.status === 'inactive') { | |
| return res.status(401).json({ | |
| error: { | |
| message: "API key is inactive.", | |
| type: "authentication_error", | |
| code: "inactive_api_key" | |
| } | |
| }); | |
| } | |
| // 更新最后使用时间 (异步非阻塞) | |
| db.prepare('UPDATE api_keys SET last_used = CURRENT_TIMESTAMP WHERE id = ?').run(keyRecord.id); | |
| // 注入用户信息到请求对象 | |
| (req as any).user = { | |
| userId: keyRecord.user_id, | |
| apiKeyId: keyRecord.id | |
| }; | |
| next(); | |
| } catch (err) { | |
| console.error('[API Auth] Key validation error:', err); | |
| res.status(500).json({ | |
| error: { | |
| message: "Internal server error during authentication.", | |
| type: "server_error", | |
| code: "internal_error" | |
| } | |
| }); | |
| } | |
| }; | |