5月30日 21:21

How to design and implement CSRF protection architecture in enterprise applications?

CSRF protection in enterprise applications needs to consider multiple aspects such as architecture, performance, scalability, and compliance to ensure effective security protection in complex environments.

Enterprise-Level CSRF Protection Architecture

1. Centralized Token Management

javascript
// Centralized Token Service class CentralizedTokenService { constructor(redisClient) { this.redis = redisClient; this.tokenExpiry = 3600; // 1 hour } async generateToken(userId) { const token = crypto.randomBytes(32).toString('hex'); const key = `csrf:${userId}:${token}`; await this.redis.setex(key, this.tokenExpiry, '1'); return token; } async validateToken(userId, token) { const key = `csrf:${userId}:${token}`; const exists = await this.redis.exists(key); if (exists) { // Delete Token after successful validation (one-time use) await this.redis.del(key); return true; } return false; } async revokeUserTokens(userId) { const pattern = `csrf:${userId}:*`; const keys = await this.redis.keys(pattern); if (keys.length > 0) { await this.redis.del(...keys); } } }

2. CSRF Protection in Distributed Environments

javascript
// Distributed CSRF Protection Middleware class DistributedCSRFProtection { constructor(tokenService, config) { this.tokenService = tokenService; this.config = config; } middleware() { return async (req, res, next) => { // Skip safe methods if (['GET', 'HEAD', 'OPTIONS'].includes(req.method)) { return next(); } // Get user ID const userId = this.getUserId(req); if (!userId) { return res.status(401).send('Unauthorized'); } // Validate Token const token = this.extractToken(req); if (!token) { return res.status(403).send('CSRF Token required'); } const isValid = await this.tokenService.validateToken(userId, token); if (!isValid) { return res.status(403).send('Invalid CSRF Token'); } next(); }; } getUserId(req) { // Get user ID from Session or JWT return req.user?.id || req.session?.userId; } extractToken(req) { // Extract Token from request header or body return req.headers['x-csrf-token'] || req.body._csrf; } }

Performance Optimization Strategies

1. Token Caching

javascript
// Use Redis to cache Tokens class CachedTokenService { constructor(redisClient, localCache) { this.redis = redisClient; this.localCache = localCache; this.ttl = 3600; } async getToken(userId) { // First check local cache const cachedToken = this.localCache.get(`csrf:${userId}`); if (cachedToken) { return cachedToken; } // Get from Redis const token = await this.redis.get(`csrf:${userId}`); if (token) { this.localCache.set(`csrf:${userId}`, token, this.ttl); return token; } // Generate new Token const newToken = crypto.randomBytes(32).toString('hex'); await this.redis.setex(`csrf:${userId}`, this.ttl, newToken); this.localCache.set(`csrf:${userId}`, newToken, this.ttl); return newToken; } }

2. Batch Token Validation

javascript
// Batch validate Tokens for multiple requests class BatchTokenValidator { constructor(tokenService) { this.tokenService = tokenService; this.batchSize = 100; } async validateBatch(requests) { const results = []; for (let i = 0; i < requests.length; i += this.batchSize) { const batch = requests.slice(i, i + this.batchSize); const batchResults = await Promise.all( batch.map(req => this.validateSingle(req)) ); results.push(...batchResults); } return results; } async validateSingle(request) { const { userId, token } = request; const isValid = await this.tokenService.validateToken(userId, token); return { userId, token, isValid, timestamp: Date.now() }; } }

High Availability Design

1. Token Service Redundancy

javascript
// Load balancing for multiple Token services class RedundantTokenService { constructor(services) { this.services = services; this.currentService = 0; } async generateToken(userId) { const service = this.getNextService(); try { return await service.generateToken(userId); } catch (error) { // Try next service return await this.generateTokenWithRetry(userId, 3); } } async generateTokenWithRetry(userId, retries) { for (let i = 0; i < retries; i++) { const service = this.getNextService(); try { return await service.generateToken(userId); } catch (error) { if (i === retries - 1) { throw error; } } } } getNextService() { const service = this.services[this.currentService]; this.currentService = (this.currentService + 1) % this.services.length; return service; } }

2. Failover

javascript
// Failure detection and failover class FailoverTokenService { constructor(primaryService, backupService) { this.primary = primaryService; this.backup = backupService; this.isPrimaryHealthy = true; this.healthCheckInterval = 30000; // 30 seconds } startHealthCheck() { setInterval(async () => { try { await this.primary.ping(); this.isPrimaryHealthy = true; } catch (error) { console.error('Primary service unhealthy:', error); this.isPrimaryHealthy = false; } }, this.healthCheckInterval); } async generateToken(userId) { if (this.isPrimaryHealthy) { try { return await this.primary.generateToken(userId); } catch (error) { console.error('Primary service failed, using backup:', error); return await this.backup.generateToken(userId); } } return await this.backup.generateToken(userId); } }

Compliance and Auditing

1. Audit Logging

javascript
// CSRF Operation Audit Logging class CSRFAuditLogger { constructor(logService) { this.logService = logService; } async logTokenGeneration(userId, token, metadata) { const auditLog = { event: 'CSRF_TOKEN_GENERATED', userId, tokenHash: this.hashToken(token), timestamp: new Date().toISOString(), metadata: { ip: metadata.ip, userAgent: metadata.userAgent, sessionId: metadata.sessionId } }; await this.logService.log(auditLog); } async logTokenValidation(userId, token, isValid, metadata) { const auditLog = { event: 'CSRF_TOKEN_VALIDATED', userId, tokenHash: this.hashToken(token), isValid, timestamp: new Date().toISOString(), metadata: { ip: metadata.ip, userAgent: metadata.userAgent, sessionId: metadata.sessionId, requestPath: metadata.requestPath } }; await this.logService.log(auditLog); } hashToken(token) { return crypto.createHash('sha256').update(token).digest('hex'); } }

2. Compliance Reporting

javascript
// Generate compliance reports class ComplianceReportGenerator { constructor(auditLogger) { this.auditLogger = auditLogger; } async generateReport(startDate, endDate) { const logs = await this.auditLogger.getLogs(startDate, endDate); return { summary: { totalTokensGenerated: logs.filter(l => l.event === 'CSRF_TOKEN_GENERATED').length, totalValidations: logs.filter(l => l.event === 'CSRF_TOKEN_VALIDATED').length, failedValidations: logs.filter(l => l.event === 'CSRF_TOKEN_VALIDATED' && !l.isValid).length, uniqueUsers: new Set(logs.map(l => l.userId)).size }, failedAttempts: this.analyzeFailedAttempts(logs), suspiciousActivity: this.detectSuspiciousActivity(logs), complianceStatus: this.checkCompliance(logs) }; } analyzeFailedAttempts(logs) { const failedLogs = logs.filter(l => l.event === 'CSRF_TOKEN_VALIDATED' && !l.isValid); return { byUser: this.groupBy(failedLogs, 'userId'), byIP: this.groupBy(failedLogs, l => l.metadata.ip), byTime: this.groupByTime(failedLogs) }; } detectSuspiciousActivity(logs) { const suspicious = []; // Detect abnormal validation failure rates const userFailureRates = this.calculateUserFailureRates(logs); Object.entries(userFailureRates).forEach(([userId, rate]) => { if (rate > 0.5) { // Failure rate over 50% suspicious.push({ type: 'HIGH_FAILURE_RATE', userId, rate }); } }); return suspicious; } checkCompliance(logs) { // Check if security standards are met const checks = { hasAuditLogs: logs.length > 0, hasTokenExpiry: true, // Need to check from configuration hasSecureTransmission: true, // Need to check from configuration hasProperValidation: true }; return { compliant: Object.values(checks).every(v => v), checks }; } }

Monitoring and Alerting

1. Real-time Monitoring

javascript
// CSRF Attack Real-time Monitoring class CSRFMonitor { constructor(metricsService, alertService) { this.metrics = metricsService; this.alerts = alertService; this.thresholds = { failedValidationsPerMinute: 10, suspiciousIPRate: 5, unusualUserAgentRate: 3 }; } async monitorValidation(userId, token, isValid, metadata) { // Record metrics this.metrics.increment('csrf.validations.total'); if (!isValid) { this.metrics.increment('csrf.validations.failed'); await this.checkFailureThresholds(userId, metadata); } else { this.metrics.increment('csrf.validations.success'); } } async checkFailureThresholds(userId, metadata) { const recentFailures = await this.getRecentFailures(60); // Last 60 seconds if (recentFailures.length > this.thresholds.failedValidationsPerMinute) { await this.alerts.send({ severity: 'HIGH', message: 'High CSRF validation failure rate detected', details: { count: recentFailures.length, timeWindow: '60s' } }); } // Check failure rate for specific IP const ipFailures = recentFailures.filter(f => f.metadata.ip === metadata.ip); if (ipFailures.length > this.thresholds.suspiciousIPRate) { await this.alerts.send({ severity: 'MEDIUM', message: 'Suspicious IP detected', details: { ip: metadata.ip, failures: ipFailures.length } }); } } }

2. Dashboard

javascript
// CSRF Security Dashboard class CSRFSecurityDashboard { constructor(monitor, reportGenerator) { this.monitor = monitor; this.reportGenerator = reportGenerator; } async getDashboardData(timeRange = '24h') { const report = await this.reportGenerator.generateReport( this.getStartDate(timeRange), new Date() ); const metrics = await this.monitor.getMetrics(timeRange); return { overview: { totalValidations: metrics.validations.total, successRate: this.calculateSuccessRate(metrics), activeUsers: report.summary.uniqueUsers }, security: { failedAttempts: report.summary.failedValidations, suspiciousActivity: report.suspiciousActivity.length, complianceStatus: report.complianceStatus.compliant }, trends: this.calculateTrends(metrics), alerts: this.getRecentAlerts() }; } }

Enterprise-level CSRF protection needs to comprehensively consider architecture, performance, availability, and compliance to build a comprehensive, reliable security protection system.

标签:CSRF