欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 高考 > 一文掌握异步web框架FastAPI(七)-- 安全(XSS 和 CSRF 防护、权限和角色控制、审计日志、使用安全的随机数生成、API 文档保护、会话管理)

一文掌握异步web框架FastAPI(七)-- 安全(XSS 和 CSRF 防护、权限和角色控制、审计日志、使用安全的随机数生成、API 文档保护、会话管理)

2024/10/25 10:33:42 来源:https://blog.csdn.net/qq_38120851/article/details/143204244  浏览:    关键词:一文掌握异步web框架FastAPI(七)-- 安全(XSS 和 CSRF 防护、权限和角色控制、审计日志、使用安全的随机数生成、API 文档保护、会话管理)

 接上篇:一文掌握异步web框架FastAPI(六)-- 安全(HTTP验证、Bearer Token、Session、OAuth2 和 OpenID Connect、HTTPS 和 TLS、速率限制)-CSDN博客

目录

九、安全

7、XSS 和 CSRF 防护

1)XSS防护

2)CSRF防护

8、安全的数据存储

9、环境变量管理

10、权限和角色控制

1)基于内存,仅用于演示

2)使用sqlite3(python已内置)

3)使用mysql

11、审计日志

12、使用安全的随机数生成

13、API 文档保护

14、会话管理


九、安全


7、XSS 和 CSRF 防护

虽然 FastAPI 本身不直接处理这些问题,但它与 Starlette 一起提供了工具来设置 cookie 的安全标志,这有助于防止 CSRF 攻击。同时,良好的编码实践和使用模板引擎(如 Jinja2)中的转义机制可以帮助防范 XSS 攻击。

1)XSS防护

XSS(Cross-Site Scripting,跨站脚本)是一种常见的网络安全漏洞,它允许攻击者在受害者的浏览器中执行恶意脚本。这些脚本可以访问在浏览器中为网站存储的所有数据,如会话cookie。如果这些cookie包含敏感信息,如认证令牌,攻击者可以利用这些信息来冒充受害者。

XSS攻击允许攻击者在用户的浏览器中执行恶意脚本。FastAPI本身不提供内置的XSS防护,但可以通过以下方式来防护:

使用模板引擎的自动转义功能:如果使用Jinja2等模板引擎,确保开启自动转义功能。Jinja2默认会自动转义所有变量输出。

为什么要转义?

在Web应用中,为了防止跨站脚本攻击(XSS),任何用户输入的内容在显示到页面上之前都应该进行转义处理。转义是指将一些特殊字符(如<, >, &, "等)转换成它们的HTML实体形式,这样浏览器在解析HTML时就不会将其当作有效的HTML标签或脚本执行。

再具体解释下:

  • 未转义的<script>标签

如果用户输入的内容包含<script>alert('XSS')</script>,并且这个内容直接被插入到HTML页面中,浏览器会解析并执行这个脚本,导致弹出一个警告框。这就是一个典型的XSS攻击。

  • 转义后的内容

如果对用户输入的内容进行转义处理,<script>alert('XSS')</script>会被转换成&lt;script&gt;alert('XSS')&lt;/script&gt;

在这种情况下,浏览器会将这些内容当作普通文本显示,而不会解析和执行其中的脚本。

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from markupsafe import escapeapp = FastAPI()
templates = Jinja2Templates(directory="templates")  # 加载模板文件, 目录名为templates@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request, user_input: str = ""):# 使用Jinja2的自动转义功能safe_input = escape(user_input)return templates.TemplateResponse("index.html", {"request": request, "user_input": safe_input})if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)

请求:

import requests# 发送包含潜在XSS攻击代码的请求
response = requests.get("http://127.0.0.1:8000/?user_input=<script>alert('XSS')</script>")
# 检查响应内容
print(response.status_code)
print(response.text)

index.html要放在templates目录下。

<!DOCTYPE html>
<html>
<head><title>XSS Protection Example</title>
</head>
<body>
<h1>Welcome to the XSS Protection Example</h1>
<p>User Input: {{ user_input }}</p>
</body>
</html>

2)CSRF防护

CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种网络攻击手段,它利用合法用户的权限来执行非授权的操作。攻击者通过伪装成合法用户向Web应用程序发送请求,从而执行非预期的操作,如更改密码、转账等。

CSRF攻击的工作原理:

  • 1、用户登录

用户登录到一个网站,并且浏览器保存了该网站的Cookie。

  • 2、攻击者构建恶意链接

攻击者构建一个包含恶意请求的URL,这个请求指向受害者的账户所在网站,并且包含一些预定义的操作,如转账、更改邮箱地址等。

  • 3、用户点击恶意链接

用户在不知情的情况下点击了包含恶意请求的URL。此时,用户的浏览器会自动附带上先前保存的Cookie(因为Cookie是自动发送的)。

  • 4、请求发送到服务器

包含恶意请求的HTTP请求被发送到了受害者的账户所在的网站,由于请求包含了正确的Cookie,所以服务器认为这是合法用户的请求。

  • 5、服务器执行请求

服务器根据请求的内容执行了相应的操作,如转账等。

CSRF攻击的示例:

假设一个银行网站有一个转账功能,URL如下:

http://bank.com/transfer?from=12345&to=67890&amount=1000

攻击者可以构建一个恶意链接:

http://bank.com/transfer?from=12345&to=attacker&amount=1000

当用户点击这个链接时,如果用户已经登录并且浏览器保存了银行的Cookie,这个请求会被发送到银行服务器,服务器会认为这是合法用户的请求,从而执行转账操作。

from fastapi import FastAPI, Request, Form, Depends, HTTPException
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware
from starlette.middleware.sessions import SessionMiddleware
from itsdangerous import URLSafeTimedSerializer
from typing import Optionalapp = FastAPI()
# 配置Session和CSRF
app.add_middleware(SessionMiddleware, secret_key="your_secret_key")
# 配置CORS
app.add_middleware(CORSMiddleware,allow_origins=["*"],allow_credentials=True,allow_methods=["*"],allow_headers=["*"],
)
templates = Jinja2Templates(directory="templates")def generate_csrf_token(request: Request):"""生成CSRF令牌。"""serializer = URLSafeTimedSerializer(request.app.state.secret_key)return serializer.dumps(request.session["session_id"], salt="csrf")def verify_csrf_token(request: Request, csrf_token: str):"""验证CSRF令牌的有效性。"""serializer = URLSafeTimedSerializer(request.app.state.secret_key)try:session_id = serializer.loads(csrf_token, salt="csrf", max_age=3600)if session_id != request.session["session_id"]:raise HTTPException(status_code=400, detail="CSRF token validation failed")except:raise HTTPException(status_code=400, detail="CSRF token validation failed")@app.on_event("startup")
def startup_event():"""应用启动事件,设置全局 secret_key。"""app.state.secret_key = "your_secret_key"  # 设置全局 secret_key@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):"""根路由处理程序,生成CSRF令牌并返回首页。"""request.session["session_id"] = request.session.get("session_id", "session_id")csrf_token = generate_csrf_token(request)return templates.TemplateResponse("index.html", {"request": request, "csrf_token": csrf_token})@app.post("/submit")
async def submit(request: Request, username: str = Form(...), csrf_token: str = Form(...)):"""处理表单提交,验证CSRF令牌并返回用户名。"""verify_csrf_token(request, csrf_token)return {"username": username}if __name__ == "__main__":import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)

请求:

import requests# 验证CSRF防护
session = requests.Session()
# 获取CSRF令牌
response = session.get("http://127.0.0.1:8000/")
csrf_token = response.text.split('name="csrf_token" value="')[1].split('"')[0]
print("\nCSRF Token:", csrf_token)
# 正确的CSRF令牌请求
data = {"username": "testuser","csrf_token": csrf_token

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com