JWT 的合规性对于企业级应用和受监管行业非常重要。以下是主要的合规要求和实现方法:
1. GDPR 合规
数据最小化原则
javascript// ❌ 不符合 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);
数据删除权
javascript// 实现用户数据删除 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 }; }
数据访问权
javascript// 实现数据导出功能 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)处理
javascript// ❌ 不符合 HIPAA: 在 JWT 中存储 PHI const token = jwt.sign({ userId: '123', patientName: 'John Doe', diagnosis: 'Hypertension', medications: ['Lisinopril', 'Amlodipine'] }, SECRET_KEY); // ✅ 符合 HIPAA: 只存储引用 ID const token = jwt.sign({ sub: '123', scope: 'patient.read', aud: 'healthcare-api' }, SECRET_KEY); // PHI 存储在安全的数据库中 const patientData = await db.get('patients', { id: '123' });
审计日志
javascript// 记录所有 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); });
最小权限原则
javascript// 实现细粒度权限控制 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 合规
不存储敏感信息
javascript// ❌ 不符合 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);
加密传输
javascript// 强制使用 HTTPS const 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(); });
安全的密钥管理
javascript// 使用 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 合规
访问控制
javascript// 实现基于角色的访问控制(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(); }; }
审计追踪
javascript// 全面的审计日志 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); });
变更管理
javascript// 记录配置变更 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 合规
信息安全策略
javascript// 实现安全策略 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; }
风险评估
javascript// 实现风险评估 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 认证系统符合各种法规和标准。