FastAPI CSP配置:内容安全策略防御XSS完全指南

【免费下载链接】fastapi FastAPI framework, high performance, easy to learn, fast to code, ready for production 【免费下载链接】fastapi 项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi

FastAPI是一个高性能、易于学习、快速编码且可用于生产环境的现代Python Web框架。在构建Web应用时,安全始终是关键考量,而内容安全策略(CSP)是防御跨站脚本攻击(XSS)的重要手段。本文将详细介绍如何在FastAPI中配置CSP,帮助开发者有效防范XSS攻击,保护应用和用户安全。

为什么需要内容安全策略(CSP)?

XSS攻击通过注入恶意脚本,窃取用户数据或执行未授权操作,是Web应用常见的安全威胁。内容安全策略(CSP)通过指定可信任的资源来源,限制浏览器加载和执行脚本,从根本上减少XSS攻击风险。

FastAPI安全防护示意图 图:内容安全策略在Web应用安全防护中的作用

FastAPI中间件机制

FastAPI基于Starlette构建,支持中间件功能,可在请求处理前后执行自定义逻辑。通过中间件,我们可以轻松添加CSP头部,实现安全策略配置。

from fastapi import FastAPI
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response

app = FastAPI()

class CSPMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next) -> Response:
        response = await call_next(request)
        # CSP配置将在这里添加
        return response

app.add_middleware(CSPMiddleware)

基础CSP策略配置

以下是一个基础的CSP配置示例,仅允许加载同源资源和特定CDN资源:

class CSPMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next) -> Response:
        response = await call_next(request)
        csp_policy = (
            "default-src 'self'; "
            "script-src 'self' https://cdn.jsdelivr.net; "
            "style-src 'self' https://cdn.jsdelivr.net; "
            "img-src 'self' data: https://cdn.jsdelivr.net; "
            "object-src 'none'; "
            "frame-src 'none'; "
            "upgrade-insecure-requests"
        )
        response.headers["Content-Security-Policy"] = csp_policy
        return response

关键指令说明:

  • default-src 'self':默认只允许加载同源资源
  • script-src:限制脚本来源
  • style-src:限制样式表来源
  • img-src:限制图片来源,允许data:协议用于内联图片
  • object-src 'none':禁止加载插件资源
  • upgrade-insecure-requests:自动将HTTP请求升级为HTTPS

进阶CSP配置与最佳实践

1. 严格策略(推荐用于生产环境)

csp_policy = (
    "default-src 'none'; "
    "script-src 'strict-dynamic' 'nonce-{nonce}'; "
    "style-src 'self' 'unsafe-inline'; "
    "img-src 'self' data:; "
    "connect-src 'self'; "
    "font-src 'self'; "
    "base-uri 'self'; "
    "form-action 'self'; "
    "frame-ancestors 'none'; "
    "upgrade-insecure-requests"
)

2. 使用Nonce防止内联脚本

import uuid

class CSPMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next) -> Response:
        nonce = str(uuid.uuid4())
        response = await call_next(request)
        csp_policy = (
            f"script-src 'nonce-{nonce}'; "
            "style-src 'self' 'unsafe-inline'; "
            # 其他指令...
        )
        response.headers["Content-Security-Policy"] = csp_policy
        return response

在模板中使用nonce:

<script nonce="{{ nonce }}">
    // 安全的内联脚本
</script>

测试与调试CSP策略

配置CSP后,建议先使用Content-Security-Policy-Report-Only头进行测试,收集违规报告而不阻止资源加载:

response.headers["Content-Security-Policy-Report-Only"] = csp_policy

违规报告将发送到指定的端点:

csp_policy += " report-uri /csp-violation-report-endpoint"

@app.post("/csp-violation-report-endpoint")
async def csp_report(report: dict):
    # 记录违规报告
    logger.warning(f"CSP Violation: {report}")
    return {"status": "ok"}

完整的FastAPI CSP中间件实现

结合上述最佳实践,以下是完整的CSP中间件实现:

import uuid
from fastapi import FastAPI, Request, Response
from starlette.middleware.base import BaseHTTPMiddleware

app = FastAPI()

class CSPMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next) -> Response:
        # 生成nonce
        nonce = str(uuid.uuid4())
        # 将nonce添加到请求状态,供模板使用
        request.state.nonce = nonce
        
        response = await call_next(request)
        
        # 配置CSP策略
        csp_policy = (
            f"default-src 'none'; "
            f"script-src 'nonce-{nonce}' https://cdn.jsdelivr.net; "
            "style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; "
            "img-src 'self' data: https://cdn.jsdelivr.net; "
            "connect-src 'self'; "
            "font-src 'self'; "
            "base-uri 'self'; "
            "form-action 'self'; "
            "frame-ancestors 'none'; "
            "upgrade-insecure-requests; "
            "report-uri /csp-report"
        )
        
        # 生产环境使用Content-Security-Policy
        # 测试阶段使用Content-Security-Policy-Report-Only
        response.headers["Content-Security-Policy"] = csp_policy
        return response

# 添加中间件
app.add_middleware(CSPMiddleware)

# CSP报告端点
@app.post("/csp-report")
async def csp_report(report: dict):
    """收集CSP违规报告"""
    print(f"CSP Violation Report: {report}")
    return {"status": "received"}

# 示例路由
@app.get("/")
async def read_root(request: Request):
    return {
        "message": "Hello World",
        "nonce": request.state.nonce
    }

总结与注意事项

  1. 逐步实施:从宽松策略开始,逐步收紧,避免影响现有功能
  2. 持续监控:通过报告端点监控违规情况,不断优化策略
  3. 平衡安全与可用性:合理配置'unsafe-inline''unsafe-eval',仅在必要时使用
  4. 结合其他安全措施:CSP应与输入验证、输出编码等安全措施结合使用

通过合理配置内容安全策略,FastAPI应用可以有效防御XSS攻击,提升Web应用的安全性。开发者应根据具体应用场景调整CSP策略,在安全与功能之间找到最佳平衡点。

更多安全最佳实践,请参考FastAPI官方文档中关于安全的章节。

【免费下载链接】fastapi FastAPI framework, high performance, easy to learn, fast to code, ready for production 【免费下载链接】fastapi 项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐