JWT 如何满足合规性要求
JWT 的合规性对于企业级应用和受监管行业非常重要。以下是主要的合规要求和实现方法:1. GDPR 合规数据最小化原则// ❌ 不符合 GDPR: 存储过多个人信息const token = jwt.sign({ userId: '123', username: 'john.doe@example.com', fullName: 'John Doe', address: '123 Main St', phone: '+1234567890', ssn: '123-45-6789' // 敏感信息}, SECRET_KEY);// ✅ 符合 GDPR: 只存储必要信息const token = jwt.sign({ sub: '123', // subject,用户唯一标识 iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + 3600}, SECRET_KEY);数据删除权// 实现用户数据删除async function deleteUserAccount(userId) { // 1. 刷新所有 token 到黑名单 await invalidateAllUserTokens(userId); // 2. 删除用户数据 await db.delete('users', { id: userId }); await db.delete('user_sessions', { userId }); // 3. 记录删除操作(审计日志) await logDataDeletion(userId, 'user_request'); return { success: true };}数据访问权// 实现数据导出功能async function exportUserData(userId) { const userData = { profile: await db.get('users', { id: userId }), sessions: await db.get('user_sessions', { userId }), activity: await db.get('user_activity', { userId }), exportDate: new Date().toISOString() }; return userData;}2. HIPAA 合规受保护健康信息(PHI)处理// ❌ 不符合 HIPAA: 在 JWT 中存储 PHIconst token = jwt.sign({ userId: '123', patientName: 'John Doe', diagnosis: 'Hypertension', medications: ['Lisinopril', 'Amlodipine']}, SECRET_KEY);// ✅ 符合 HIPAA: 只存储引用 IDconst token = jwt.sign({ sub: '123', scope: 'patient.read', aud: 'healthcare-api'}, SECRET_KEY);// PHI 存储在安全的数据库中const patientData = await db.get('patients', { id: '123' });审计日志// 记录所有 PHI 访问async function logPHIAccess(userId, patientId, action) { await db.insert('audit_log', { userId, patientId, action, timestamp: new Date().toISOString(), ip: req.ip, userAgent: req.headers['user-agent'], accessedFields: ['diagnosis', 'medications'] });}// 使用示例app.get('/api/patients/:id', authMiddleware, async (req, res) => { const patient = await db.get('patients', { id: req.params.id }); // 记录访问 await logPHIAccess(req.user.userId, req.params.id, 'READ'); res.json(patient);});最小权限原则// 实现细粒度权限控制function requirePHIAccess(requiredScope) { return (req, res, next) => { const userScope = req.user.scope || []; if (!userScope.includes(requiredScope)) { return res.status(403).json({ error: 'INSUFFICIENT_PERMISSIONS', message: 'You do not have permission to access this resource' }); } next(); };}// 使用示例app.get('/api/patients/:id', authMiddleware, requirePHIAccess('patient.read'), async (req, res) => { const patient = await db.get('patients', { id: req.params.id }); res.json(patient); });3. PCI DSS 合规不存储敏感信息// ❌ 不符合 PCI DSS: 在 JWT 中存储卡号const token = jwt.sign({ userId: '123', cardNumber: '4111111111111111', expiry: '12/25', cvv: '123'}, SECRET_KEY);// ✅ 符合 PCI DSS: 只存储令牌化后的引用const token = jwt.sign({ sub: '123', paymentToken: 'tok_1abc2def3ghi', scope: 'payment.process'}, SECRET_KEY);加密传输// 强制使用 HTTPSconst https = require('https');const fs = require('fs');const options = { key: fs.readFileSync('private-key.pem'), cert: fs.readFileSync('certificate.pem'), ca: fs.readFileSync('ca-bundle.crt')};const server = https.createServer(options, app);// HTTP 到 HTTPS 重定向app.use((req, res, next) => { if (!req.secure) { return res.redirect(`https://${req.headers.host}${req.url}`); } next();});安全的密钥管理// 使用 AWS KMS 管理密钥const AWS = require('aws-sdk');const kms = new AWS.KMS();async function encryptData(data) { const params = { KeyId: process.env.KMS_KEY_ID, Plaintext: Buffer.from(data) }; const result = await kms.encrypt(params).promise(); return result.CiphertextBlob.toString('base64');}async function decryptData(encryptedData) { const params = { CiphertextBlob: Buffer.from(encryptedData, 'base64') }; const result = await kms.decrypt(params).promise(); return result.Plaintext.toString();}4. SOC 2 合规访问控制// 实现基于角色的访问控制(RBAC)const roles = { admin: ['read', 'write', 'delete', 'manage'], user: ['read', 'write'], guest: ['read']};function checkPermission(user, requiredPermission) { const userRole = user.role || 'guest'; const userPermissions = roles[userRole] || []; return userPermissions.includes(requiredPermission);}// 中间件function requirePermission(permission) { return (req, res, next) => { if (!checkPermission(req.user, permission)) { return res.status(403).json({ error: 'FORBIDDEN', message: 'Insufficient permissions' }); } next(); };}审计追踪// 全面的审计日志async function auditLog(event, data) { const logEntry = { event, data, timestamp: new Date().toISOString(), userId: data.userId, ipAddress: data.ip, userAgent: data.userAgent, sessionId: data.sessionId }; // 存储到不可变的日志存储 await appendToAuditLog(logEntry); // 同时发送到 SIEM 系统 await sendToSIEM(logEntry);}// 使用示例app.post('/api/users', authMiddleware, async (req, res) => { const user = await createUser(req.body); await auditLog('USER_CREATED', { userId: req.user.userId, targetUserId: user.id, ip: req.ip, userAgent: req.headers['user-agent'] }); res.json(user);});变更管理// 记录配置变更async function logConfigChange(configKey, oldValue, newValue, userId) { await db.insert('config_changes', { configKey, oldValue, newValue, userId, timestamp: new Date().toISOString(), changeType: 'MODIFICATION' });}// 使用示例async function updateJWTConfig(newConfig) { const oldConfig = await getCurrentJWTConfig(); await logConfigChange( 'jwt_config', oldConfig, newConfig, req.user.userId ); await saveJWTConfig(newConfig);}5. ISO 27001 合规信息安全策略// 实现安全策略const securityPolicies = { passwordPolicy: { minLength: 12, requireUppercase: true, requireLowercase: true, requireNumbers: true, requireSpecialChars: true, maxAge: 90 // days }, tokenPolicy: { accessTokenExpiry: 900, // 15 minutes refreshTokenExpiry: 604800, // 7 days maxConcurrentSessions: 5 }, sessionPolicy: { idleTimeout: 1800, // 30 minutes absoluteTimeout: 28800 // 8 hours }};// 验证密码策略function validatePassword(password) { const policy = securityPolicies.passwordPolicy; if (password.length < policy.minLength) { throw new Error('Password too short'); } if (policy.requireUppercase && !/[A-Z]/.test(password)) { throw new Error('Password must contain uppercase letters'); } // ... 其他验证 return true;}风险评估// 实现风险评估async function assessSecurityRisk(userId, action) { const riskFactors = { unusualLocation: await checkUnusualLocation(userId), unusualTime: await checkUnusualTime(userId), multipleFailedAttempts: await checkFailedAttempts(userId), newDevice: await checkNewDevice(userId) }; const riskScore = Object.values(riskFactors) .filter(Boolean) .length; if (riskScore >= 2) { // 高风险,需要额外验证 return { risk: 'HIGH', requireMFA: true }; } return { risk: 'LOW', requireMFA: false };}// 使用示例app.post('/auth/login', async (req, res) => { const { username, password } = req.body; const user = await validateUser(username, password); const riskAssessment = await assessSecurityRisk(user.id, 'LOGIN'); if (riskAssessment.requireMFA) { return res.json({ requireMFA: true, mfaMethods: ['sms', 'totp'] }); } const token = generateToken(user); res.json({ token });});6. 合规检查清单GDPR 检查清单[ ] 实施数据最小化原则[ ] 提供数据访问权[ ] 实现数据删除权[ ] 获得明确的同意[ ] 实施数据保护措施[ ] 记录数据处理活动[ ] 指定数据保护官(DPO)HIPAA 检查清单[ ] 保护 PHI 的机密性[ ] 实施访问控制[ ] 记录所有 PHI 访问[ ] 实施最小权限原则[ ] 定期进行风险评估[ ] 签署商业伙伴协议(BAA)[ ] 培训员工安全意识PCI DSS 检查清单[ ] 不存储完整的卡号[ ] 使用令牌化技术[ ] 加密传输数据[ ] 使用强加密算法[ ] 定期更新密钥[ ] 实施访问控制[ ] 进行定期安全测试SOC 2 检查清单[ ] 实施访问控制[ ] 记录所有系统活动[ ] 实施变更管理流程[ ] 定期进行审计[ ] 建立事件响应计划[ ] 进行员工背景调查[ ] 定期进行安全培训ISO 27001 检查清单[ ] 建立信息安全策略[ ] 实施风险评估[ ] 建立访问控制[ ] 实施密码策略[ ] 定期进行安全审计[ ] 建立事件响应流程[ ] 持续改进安全措施7. 最佳实践合规性最佳实践了解适用的法规: 确定哪些合规要求适用于你的业务实施最小权限: 只授予必要的访问权限记录所有活动: 维护完整的审计日志定期审计: 定期检查合规性培训员工: 确保员工了解合规要求使用加密: 保护敏感数据实施访问控制: 限制对敏感信息的访问建立事件响应: 准备应对安全事件定期更新: 保持系统和策略的最新寻求专业建议: 必要时咨询合规专家通过遵循这些合规要求,可以确保 JWT 认证系统符合各种法规和标准。