SecurityHeadersConfiguration security-headers-configuration

这个skill提供了如何配置HTTP安全头部的指南,包括CSP、HSTS、X-Frame-Options和XSS保护等,用于增强Web应用程序的安全性,防御XSS攻击、点击劫持等浏览器端的安全威胁。

安全审计 0 次安装 0 次浏览 更新于 3/4/2026

安全头部配置

概述

实施全面的HTTP安全头部以保护Web应用程序免受XSS、点击劫持、MIME嗅探和其他基于浏览器的攻击。

何时使用

  • 新Web应用程序部署
  • 安全审计补救
  • 合规性要求
  • 浏览器安全硬化
  • API安全
  • 静态站点保护

实施示例

1. Node.js/Express安全头部

// security-headers.js
const helmet = require('helmet');

function configureSecurityHeaders(app) {
  // 全面Helmet配置
  app.use(helmet({
    // 内容安全策略
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: [
          "'self'",
          "'unsafe-inline'", // 生产中移除
          "https://cdn.example.com",
          "https://www.google-analytics.com"
        ],
        styleSrc: [
          "'self'",
          "'unsafe-inline'",
          "https://fonts.googleapis.com"
        ],
        fontSrc: [
          "'self'",
          "https://fonts.gstatic.com"
        ],
        imgSrc: [
          "'self'",
          "data:",
          "https:",
          "blob:"
        ],
        connectSrc: [
          "'self'",
          "https://api.example.com"
        ],
        frameSrc: ["'none'"],
        objectSrc: ["'none'"],
        upgradeInsecureRequests: []
      }
    },

    // 严格传输安全
    hsts: {
      maxAge: 31536000, // 1年
      includeSubDomains: true,
      preload: true
    },

    // X-Frame-Options
    frameguard: {
      action: 'deny'
    },

    // X-Content-Type-Options
    noSniff: true,

    // X-XSS-Protection
    xssFilter: true,

    // Referrer-Policy
    referrerPolicy: {
      policy: 'strict-origin-when-cross-origin'
    },

    // Permissions-Policy (原Feature-Policy)
    permittedCrossDomainPolicies: {
      permittedPolicies: 'none'
    }
  }));

  // 额外自定义头部
  app.use((req, res, next) => {
    // Permissions Policy
    res.setHeader(
      'Permissions-Policy',
      'geolocation=(), microphone=(), camera=(), payment=(), usb=()'
    );

    // Expect-CT
    res.setHeader(
      'Expect-CT',
      'max-age=86400, enforce'
    );

    // 跨源策略
    res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
    res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
    res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');

    // 移除powered-by头部
    res.removeHeader('X-Powered-By');

    next();
  });
}

// CSP违规报告器
app.post('/api/csp-report', express.json({ type: 'application/csp-report' }), (req, res) => {
  const report = req.body['csp-report'];

  console.error('CSP Violation:', {
    documentUri: report['document-uri'],
    violatedDirective: report['violated-directive'],
    blockedUri: report['blocked-uri'],
    sourceFile: report['source-file'],
    lineNumber: report['line-number']
  });

  // 存储在数据库或发送到监控服务
  // monitoringService.logCSPViolation(report);

  res.status(204).end();
});

module.exports = { configureSecurityHeaders };

2. Nginx安全头部配置

# nginx-security-headers.conf

server {
    listen 443 ssl http2;
    server_name example.com;

    # SSL配置
    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # 安全头部
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

    # 内容安全策略
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-uri /api/csp-report" always;

    # 跨源策略
    add_header Cross-Origin-Embedder-Policy "require-corp" always;
    add_header Cross-Origin-Opener-Policy "same-origin" always;
    add_header Cross-Origin-Resource-Policy "same-origin" always;

    # Expect-CT
    add_header Expect-CT "max-age=86400, enforce" always;

    # 隐藏服务器版本
    server_tokens off;

    location / {
        root /var/www/html;
        index index.html;
    }

    # API端点
    location /api/ {
        proxy_pass http://backend:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 移除后端头部可能会泄露信息
        proxy_hide_header X-Powered-By;
        proxy_hide_header Server;
    }
}

# 重定向HTTP到HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

3. Python Flask安全头部

# security_headers.py
from flask import Flask, make_response
from functools import wraps

app = Flask(__name__)

def add_security_headers(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        resp = make_response(f(*args, **kwargs))

        # 严格传输安全
        resp.headers['Strict-Transport-Security'] = \
            'max-age=31536000; includeSubDomains; preload'

        # X-Frame-Options
        resp.headers['X-Frame-Options'] = 'DENY'

        # X-Content-Type-Options
        resp.headers['X-Content-Type-Options'] = 'nosniff'

        # X-XSS-Protection
        resp.headers['X-XSS-Protection'] = '1; mode=block'

        # Referrer-Policy
        resp.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'

        # Permissions-Policy
        resp.headers['Permissions-Policy'] = \
            'geolocation=(), microphone=(), camera=(), payment=()'

        # 内容安全策略
        csp = {
            "default-src": ["'self'"],
            "script-src": ["'self'", "https://cdn.example.com"],
            "style-src": ["'self'", "'unsafe-inline'"],
            "img-src": ["'self'", "data:", "https:"],
            "font-src": ["'self'"],
            "connect-src": ["'self'", "https://api.example.com"],
            "frame-ancestors": ["'none'"],
            "base-uri": ["'self'"],
            "form-action": ["'self'"],
            "report-uri": ["/api/csp-report"]
        }

        csp_string = "; ".join([
            f"{key} {' '.join(values)}"
            for key, values in csp.items()
        ])

        resp.headers['Content-Security-Policy'] = csp_string

        # 跨源策略
        resp.headers['Cross-Origin-Embedder-Policy'] = 'require-corp'
        resp.headers['Cross-Origin-Opener-Policy'] = 'same-origin'
        resp.headers['Cross-Origin-Resource-Policy'] = 'same-origin'

        # Expect-CT
        resp.headers['Expect-CT'] = 'max-age=86400, enforce'

        # 移除服务器头部
        resp.headers.pop('Server', None)

        return resp

    return decorated_function

# 应用于所有路由
@app.after_request
def apply_security_headers(response):
    # 同上头部
    response.headers['Strict-Transport-Security'] = \
        'max-age=31536000; includeSubDomains; preload'
    response.headers['X-Frame-Options'] = 'DENY'
    response.headers['X-Content-Type-Options'] = 'nosniff'
    response.headers['X-XSS-Protection'] = '1; mode=block'

    return response

# CSP违规端点
@app.route('/api/csp-report', methods=['POST'])
def csp_report():
    report = request.get_json()

    print(f"CSP Violation: {report}")

    # 记录到监控服务
    # monitoring.log_csp_violation(report)

    return '', 204

if __name__ == '__main__':
    # 仅支持HTTPS运行
    app.run(ssl_context='adhoc', port=443)

4. Apache .htaccess配置

# .htaccess - Apache安全头部

# 严格传输安全
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

# X-Frame-Options
Header always set X-Frame-Options "DENY"

# X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"

# X-XSS-Protection
Header always set X-XSS-Protection "1; mode=block"

# Referrer-Policy
Header always set Referrer-Policy "strict-origin-when-cross-origin"

# Permissions-Policy
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"

# 内容安全策略
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none'"

# 跨源策略
Header always set Cross-Origin-Embedder-Policy "require-corp"
Header always set Cross-Origin-Opener-Policy "same-origin"
Header always set Cross-Origin-Resource-Policy "same-origin"

# 移除服务器签名
ServerSignature Off
Header unset Server
Header unset X-Powered-By

# 强制HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

5. 安全头部测试脚本

// test-security-headers.js
const axios = require('axios');

async function testSecurityHeaders(url) {
  console.log(`
=== Testing Security Headers for ${url} ===
`);

  try {
    const response = await axios.get(url, {
      validateStatus: () => true
    });

    const headers = response.headers;

    const tests = {
      'Strict-Transport-Security': {
        present: !!headers['strict-transport-security'],
        value: headers['strict-transport-security'],
        recommended: 'max-age=31536000; includeSubDomains; preload'
      },
      'X-Frame-Options': {
        present: !!headers['x-frame-options'],
        value: headers['x-frame-options'],
        recommended: 'DENY or SAMEORIGIN'
      },
      'X-Content-Type-Options': {
        present: !!headers['x-content-type-options'],
        value: headers['x-content-type-options'],
        recommended: 'nosniff'
      },
      'X-XSS-Protection': {
        present: !!headers['x-xss-protection'],
        value: headers['x-xss-protection'],
        recommended: '1; mode=block'
      },
      'Content-Security-Policy': {
        present: !!headers['content-security-policy'],
        value: headers['content-security-policy'],
        recommended: 'Define strict CSP'
      },
      'Referrer-Policy': {
        present: !!headers['referrer-policy'],
        value: headers['referrer-policy'],
        recommended: 'strict-origin-when-cross-origin'
      },
      'Permissions-Policy': {
        present: !!headers['permissions-policy'],
        value: headers['permissions-policy'],
        recommended: 'Restrict dangerous features'
      }
    };

    let passed = 0;
    let failed = 0;

    for (const [header, test] of Object.entries(tests)) {
      if (test.present) {
        console.log(`✓ ${header}: ${test.value}`);
        passed++;
      } else {
        console.log(`✗ ${header}: MISSING`);
        console.log(`  Recommended: ${test.recommended}`);
        failed++;
      }
    }

    console.log(`
=== Summary ===`);
    console.log(`Passed: ${passed}/${Object.keys(tests).length}`);
    console.log(`Failed: ${failed}/${Object.keys(tests).length}`);

    const score = (passed / Object.keys(tests).length) * 100;
    console.log(`Security Score: ${score.toFixed(0)}%`);

  } catch (error) {
    console.error('Error testing headers:', error.message);
  }
}

// 使用方法
testSecurityHeaders('https://example.com');

最佳实践

✅ DO

  • 处处使用HTTPS
  • 实施严格的CSP
  • 启用带有预加载的HSTS
  • 使用X-Frame-Options阻止框架
  • 防止MIME嗅探
  • 报告CSP违规
  • 定期测试头部
  • 使用安全扫描器

❌ DON’T

  • 允许CSP中的unsafe-inline
  • 在子域上跳过HSTS
  • 忽略CSP违规
  • 使用过于宽松的政策
  • 忘记测试更改

安全头部清单

  • [ ] Strict-Transport-Security
  • [ ] Content-Security-Policy
  • [ ] X-Frame-Policy
  • [ ] X-Content-Type-Options
  • [ ] X-XSS-Protection
  • [ ] Referrer-Policy
  • [ ] Permissions-Policy
  • [ ] 跨源策略
  • [ ] Expect-CT
  • [ ] 移除服务器签名

测试工具

资源