乐闻世界logo
搜索文章和话题

What security issues should be noted when using axios? How to prevent XSS, CSRF, and other attacks?

3月6日 23:03

When using axios for HTTP requests, you need to pay attention to various security issues, including XSS, CSRF, sensitive information leakage, etc.

1. XSS (Cross-Site Scripting) Protection

Problem Description

XSS attacks may inject malicious scripts through axios response data.

Protection Measures

javascript
// 1. Response data escaping import DOMPurify from 'dompurify'; axios.interceptors.response.use( (response) => { // XSS filtering for response data if (response.data && typeof response.data === 'object') { response.data = sanitizeData(response.data); } return response; } ); function sanitizeData(data) { if (typeof data === 'string') { return DOMPurify.sanitize(data); } if (Array.isArray(data)) { return data.map(sanitizeData); } if (typeof data === 'object' && data !== null) { return Object.keys(data).reduce((acc, key) => { acc[key] = sanitizeData(data[key]); return acc; }, {}); } return data; } // 2. Set secure Content-Type axios.defaults.headers.common['Content-Type'] = 'application/json; charset=utf-8'; // 3. Prevent JSON injection axios.interceptors.request.use( (config) => { if (config.data && typeof config.data === 'object') { // Ensure sending JSON, not executable JavaScript config.data = JSON.stringify(config.data); } return config; } );

2. CSRF (Cross-Site Request Forgery) Protection

Problem Description

Attackers induce users to perform unintended actions on authenticated websites.

Protection Measures

javascript
// 1. Use CSRF Token const api = axios.create({ xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', withCredentials: true // Allow carrying cookies }); // 2. Manually add CSRF Token api.interceptors.request.use((config) => { // Get from meta tag const token = document.querySelector('meta[name="csrf-token"]')?.content; if (token) { config.headers['X-CSRF-Token'] = token; } // Or get from cookie const csrfToken = getCookie('csrfToken'); if (csrfToken) { config.headers['X-CSRF-Token'] = csrfToken; } return config; }); // 3. Double Cookie Verification api.interceptors.request.use((config) => { const sessionId = getCookie('sessionId'); const csrfToken = getCookie('csrfToken'); if (sessionId && csrfToken) { config.headers['X-CSRF-Token'] = csrfToken; // Verify token and session association } return config; }); // 4. SameSite Cookie Setting // Server setting: Set-Cookie: sessionId=xxx; SameSite=Strict; Secure; HttpOnly

3. Sensitive Information Protection

Token Secure Storage

javascript
// ❌ Don't store directly in localStorage (XSS risk) localStorage.setItem('token', token); // ✅ Use httpOnly cookie (recommended) // Server setting: Set-Cookie: token=xxx; HttpOnly; Secure; SameSite=Strict // ✅ If must use localStorage, add additional security measures const secureStorage = { set(key, value) { // Add timestamp and signature const data = { value, timestamp: Date.now(), signature: generateSignature(value) }; localStorage.setItem(key, JSON.stringify(data)); }, get(key) { const item = localStorage.getItem(key); if (!item) return null; try { const data = JSON.parse(item); // Verify signature if (data.signature !== generateSignature(data.value)) { this.remove(key); return null; } // Check expiration (e.g., 24 hours) if (Date.now() - data.timestamp > 24 * 60 * 60 * 1000) { this.remove(key); return null; } return data.value; } catch { return null; } }, remove(key) { localStorage.removeItem(key); } }; function generateSignature(value) { // Use simple hash or HMAC return btoa(value + SECRET_KEY); }

Sensitive Information in Request Headers

javascript
// 1. Avoid passing sensitive information in URL // ❌ Wrong axios.get(`/api/user?password=${password}`); // ✅ Correct axios.post('/api/user', { password }); // 2. Request header encryption import CryptoJS from 'crypto-js'; axios.interceptors.request.use((config) => { // Encrypt sensitive headers if (config.headers.Authorization) { config.headers['X-Encrypted'] = '1'; // Or use custom encryption // config.headers.Authorization = encrypt(config.headers.Authorization); } return config; }); // 3. Limit header exposure // Server setting: Access-Control-Expose-Headers: limited-headers

4. HTTPS and Certificate Verification

javascript
// 1. Force HTTPS const api = axios.create({ baseURL: 'https://api.example.com', // Must use HTTPS }); // 2. Certificate verification in Node.js environment const https = require('https'); const fs = require('fs'); const api = axios.create({ httpsAgent: new https.Agent({ // Don't set to false in production rejectUnauthorized: true, // Use custom CA certificate ca: fs.readFileSync('path/to/ca-cert.pem') }) }); // 3. Certificate Pinning const httpsAgent = new https.Agent({ checkServerIdentity: (host, cert) => { const expectedFingerprint = 'AA:BB:CC:DD:EE:FF:...'; const actualFingerprint = cert.fingerprint256; if (actualFingerprint !== expectedFingerprint) { throw new Error('Certificate fingerprint mismatch'); } } });

5. Request Parameter Validation

javascript
import Joi from 'joi'; // 1. Request parameter validation const requestSchema = Joi.object({ email: Joi.string().email().required(), password: Joi.string().min(8).max(32).required(), age: Joi.number().integer().min(0).max(150) }); axios.interceptors.request.use((config) => { if (config.data) { const { error } = requestSchema.validate(config.data); if (error) { return Promise.reject(new Error(`Validation error: ${error.message}`)); } } return config; }); // 2. URL parameter encoding axios.interceptors.request.use((config) => { if (config.params) { config.params = Object.keys(config.params).reduce((acc, key) => { acc[key] = encodeURIComponent(config.params[key]); return acc; }, {}); } return config; }); // 3. Prevent SQL injection (frontend level) function sanitizeInput(input) { if (typeof input !== 'string') return input; // Remove or escape dangerous characters return input .replace(/[;\"']/g, '') .replace(/--/g, '') .replace(/\/\*/g, '') .replace(/\*\//g, ''); } axios.interceptors.request.use((config) => { if (config.data) { config.data = Object.keys(config.data).reduce((acc, key) => { acc[key] = sanitizeInput(config.data[key]); return acc; }, {}); } return config; });

6. Response Security Verification

javascript
// 1. Verify response content type axios.interceptors.response.use( (response) => { const contentType = response.headers['content-type']; // Ensure response is JSON if (!contentType || !contentType.includes('application/json')) { return Promise.reject(new Error('Invalid content type')); } return response; } ); // 2. Verify response data signature axios.interceptors.response.use( (response) => { const signature = response.headers['x-response-signature']; const data = JSON.stringify(response.data); if (signature && !verifySignature(data, signature)) { return Promise.reject(new Error('Invalid response signature')); } return response; } ); function verifySignature(data, signature) { const expectedSignature = CryptoJS.HmacSHA256(data, SECRET_KEY).toString(); return signature === expectedSignature; }

7. Security Header Settings

javascript
// Send security-related request headers const secureApi = axios.create({ headers: { // Prevent MIME type sniffing 'X-Content-Type-Options': 'nosniff', // Enable XSS filter 'X-XSS-Protection': '1; mode=block', // Clickjacking protection 'X-Frame-Options': 'DENY', // Content Security Policy 'Content-Security-Policy': "default-src 'self'", // Strict Transport Security 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains' } });

8. Logging and Monitoring

javascript
// Security logging axios.interceptors.request.use((config) => { // Log request (excluding sensitive information) securityLogger.info({ type: 'request', url: config.url, method: config.method, timestamp: new Date().toISOString(), // Don't log sensitive information in headers or data }); return config; }); axios.interceptors.response.use( (response) => { securityLogger.info({ type: 'response', url: response.config.url, status: response.status, timestamp: new Date().toISOString() }); return response; }, (error) => { securityLogger.error({ type: 'error', url: error.config?.url, status: error.response?.status, message: error.message, timestamp: new Date().toISOString() }); return Promise.reject(error); } ); // Anomaly detection function detectAnomalies(response) { // Detect unusually large responses const responseSize = JSON.stringify(response.data).length; if (responseSize > 10 * 1024 * 1024) { // 10MB securityLogger.warn('Unusually large response detected'); } // Detect abnormal response times const duration = response.config.metadata?.duration; if (duration > 30000) { // 30 seconds securityLogger.warn('Slow response detected'); } }

9. Complete Security Configuration Example

javascript
import axios from 'axios'; import DOMPurify from 'dompurify'; import CryptoJS from 'crypto-js'; const secureApi = axios.create({ baseURL: 'https://api.example.com', timeout: 10000, withCredentials: true, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', headers: { 'Content-Type': 'application/json; charset=utf-8', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block' } }); // Request interceptor - security processing secureApi.interceptors.request.use( (config) => { // 1. Parameter validation and sanitization if (config.data) { config.data = sanitizeData(config.data); } // 2. Add request signature const timestamp = Date.now(); config.headers['X-Timestamp'] = timestamp; config.headers['X-Signature'] = generateRequestSignature(config, timestamp); // 3. Log security event logSecurityEvent('request', config); return config; }, (error) => Promise.reject(error) ); // Response interceptor - security processing secureApi.interceptors.response.use( (response) => { // 1. Verify response signature if (!verifyResponseSignature(response)) { return Promise.reject(new Error('Invalid response signature')); } // 2. XSS sanitization if (response.data) { response.data = sanitizeData(response.data); } // 3. Anomaly detection detectAnomalies(response); return response; }, (error) => { logSecurityEvent('error', null, error); return Promise.reject(error); } ); export default secureApi;

Security Checklist

  • Use HTTPS for all data transmission
  • Enable CSRF protection
  • Store sensitive information using httpOnly Cookie
  • Validate and sanitize input data
  • Filter output data for XSS
  • Set appropriate security headers
  • Implement request/response signature verification
  • Log security events and monitor anomalies
  • Regularly update dependency packages
  • Conduct security audits and penetration testing
标签:JavaScript前端Axios