0

0

深入理解Flask中的CSRF保护与Flask-WTF表单实践

碧海醫心

碧海醫心

发布时间:2025-11-18 12:55:02

|

516人浏览过

|

来源于php中文网

原创

深入理解Flask中的CSRF保护与Flask-WTF表单实践

本文深入探讨了flask应用中跨站请求伪造(csrf)攻击的原理与防御机制。我们将详细解释csrf攻击如何利用用户会话执行未授权操作,以及flask-wtf如何通过csrf令牌自动提供保护。内容涵盖csrf保护的适用场景(主要针对post请求而非get请求),以及如何在flask-wtf中使用空表单来集成csrf令牌,确保应用安全性。

1. 跨站请求伪造 (CSRF) 攻击原理

跨站请求伪造(Cross-Site Request Forgery, CSRF)是一种常见的网络攻击,其核心在于诱导受害者在不知情的情况下,向其已登录的Web应用程序发送伪造的请求。攻击者利用用户在目标网站上的有效认证会话(通常通过Cookie维护),迫使用户的浏览器执行用户本不打算执行的操作,例如更改邮箱、密码、发布内容或进行资金转账等。

攻击示例解析: 假设您的Flask应用中有一个功能,允许已登录用户通过访问特定URL来更新其邮箱地址,例如 https://mygreatapp.com/updatemail?email=new_email@example.com。当用户登录到 mygreatapp.com 后,其浏览器会持有该站点的有效会话Cookie。

攻击者可以构造一个恶意页面,并在其中嵌入一个看似无害的元素,例如一个 深入理解Flask中的CSRF保护与Flask-WTF表单实践 标签,其 src 属性指向一个恶意URL:

@@##@@

当已登录的用户访问攻击者控制的这个恶意页面时,用户的浏览器会自动加载 深入理解Flask中的CSRF保护与Flask-WTF表单实践 标签中的 src URL。由于浏览器在发送请求时会自动携带 mygreatapp.com 的会话Cookie,服务器会认为这是一个合法用户发起的请求,并执行邮箱更新操作,将用户的邮箱更改为 attacker@malicious.com。攻击者随后便可利用“忘记密码”功能重置密码,从而劫持用户账户。

2. CSRF 保护机制

CSRF保护的核心在于引入一个只有合法用户才能提供、且攻击者难以猜测或获取的秘密令牌(CSRF Token)。其工作流程如下:

  1. 服务器生成令牌: 当用户请求一个包含表单的页面时,服务器会生成一个唯一、随机且与用户当前会话绑定的CSRF令牌。这个令牌通常会存储在用户会话中,并通过一个隐藏字段嵌入到发送给用户的HTML表单中。
  2. 客户端提交令牌: 用户提交表单时,浏览器会将表单数据连同这个隐藏的CSRF令牌一起发送回服务器。
  3. 服务器验证令牌: 服务器接收到请求后,会验证提交的CSRF令牌是否与当前用户会话中存储的令牌一致。
    • 如果令牌一致,服务器认为请求是合法的,并允许执行相应的操作。
    • 如果令牌不一致或缺失,服务器会判断请求为伪造的,并拒绝该请求,从而阻止攻击。

由于攻击者无法预测或获取到这个随机生成的、与用户会话绑定的令牌,因此无法构造出带有正确令牌的恶意请求,从而有效阻止CSRF攻击。

3. Flask-WTF 与 CSRF 保护实践

Flask-WTF 是 Flask 框架的一个扩展,它集成了 WTForms 库,为表单处理提供了极大的便利,包括内置的CSRF保护。

3.1 CSRF 保护的适用场景

  • HTTP 方法: CSRF保护主要针对会改变服务器状态的请求,例如 POST、PUT、DELETE 等。对于不会改变服务器状态的 GET 和 HEAD 请求,通常不需要CSRF保护。这是因为 GET 请求被设计为幂等的、可缓存的,且不应产生副作用。如果一个 GET 请求被设计为改变服务器状态,那本身就违反了HTTP规范,应将其改为 POST 或其他适当的方法。
  • 用户状态: CSRF保护并非只针对已登录用户。任何可能导致服务器状态改变的操作,无论用户是否登录(例如匿名用户提交评论、注册账户等),都应考虑CSRF保护,以防止恶意用户利用这些接口进行滥用。

3.2 在 Flask 应用中启用 Flask-WTF CSRF 保护

Flask-WTF 默认开启了CSRF保护。你只需确保在 Flask 应用配置中设置了 SECRET_KEY,并初始化 CSRFProtect 扩展。

app.py 配置示例:

讯飞听见会议
讯飞听见会议

科大讯飞推出的AI智能会议系统

下载
from flask import Flask
from flask_wtf.csrf import CSRFProtect

app = Flask(__name__)
# 必须设置一个强密钥,用于签名会话Cookie和CSRF令牌
# 生产环境中应通过环境变量或其他安全方式配置
app.config['SECRET_KEY'] = 'your_very_strong_and_random_secret_key' 

# 初始化 CSRFProtect 扩展
csrf = CSRFProtect(app)

# ... 其他路由和视图函数定义

3.3 使用空 Flask-WTF 表单集成 CSRF 令牌

即使表单不包含任何用户输入字段,你也可以利用 Flask-WTF 来生成并管理CSRF令牌。这对于那些仅用于触发特定操作(如确认删除、触发异步任务等)而无需额外用户输入的表单非常有用。

forms.py 示例:

from flask_wtf import FlaskForm

class EmptyForm(FlaskForm):
    """
    一个不包含任何用户输入字段的空表单。
    FlaskForm 会自动处理 CSRF 令牌的生成和验证。
    """
    pass

routes.py 示例:

from flask import render_template, request, redirect, url_for, flash
from app import app # 假设 app 实例在 app.py 中定义
from forms import EmptyForm

@app.route('/confirm_action', methods=['GET', 'POST'])
def confirm_action():
    form = EmptyForm()
    if request.method == 'POST':
        # form.validate_on_submit() 会自动验证 CSRF 令牌
        if form.validate_on_submit():
            # CSRF 令牌已验证通过,执行需要保护的操作
            # 例如:删除用户数据、发送通知等
            flash('操作已成功执行!', 'success')
            return redirect(url_for('index')) # 重定向到其他页面
        else:
            # CSRF 令牌无效或表单验证失败
            flash('操作失败,安全验证不通过,请重试。', 'danger')

    # 对于 GET 请求或 POST 请求验证失败的情况,渲染表单页面
    return render_template('confirm_action.html', form=form)

# 假设有一个首页路由用于重定向
@app.route('/')
def index():
    return "

欢迎来到首页!

点击 这里 确认操作。

"

confirm_action.html 示例:




    
    
    确认操作
    


    

确认您的操作

您即将执行一个重要操作。请点击确认按钮继续。

{{ form.csrf_token }}
{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %}
    {% for category, message in messages %}
  • {{ message }}
  • {% endfor %}
{% endif %} {% endwith %}

关于原问题中 method="GET" 表单的说明: 在原始问题提供的HTML代码中,表单的 method 属性被设置为 GET。虽然 Flask-WTF 允许你在 GET 表单中渲染 csrf_token,但这通常不是推荐的做法。CSRF保护主要用于防止恶意 POST 请求,因为 GET 请求不应改变服务器状态。如果一个 GET 请求携带了CSRF令牌并改变了状态,这表明应用设计上存在缺陷。如果你的表单确实需要改变状态,请务必将其 method 设置为 POST。如果表单仅用于显示信息或不改变服务器状态,则不需要CSRF保护。

4. 注意事项与最佳实践

  • SECRET_KEY 的安全性: SECRET_KEY 是 Flask 应用安全的核心。它用于签名会话Cookie和CSRF令牌。务必使用一个长、随机且复杂的密钥,并且绝不能将其硬编码在代码中或提交到版本控制系统。在生产环境中,应通过环境变量或其他安全配置方式进行管理。
  • 严格遵守HTTP方法语义: 严格遵守HTTP方法语义,不要在 GET 请求中执行任何会改变服务器状态的操作。如果需要改变状态,请使用 POST 请求,并辅以CSRF保护。
  • 理解 form.validate_on_submit(): 这个方法会在 POST 请求时自动验证
深入理解Flask中的CSRF保护与Flask-WTF表单实践

相关专题

更多
Python Flask框架
Python Flask框架

本专题专注于 Python 轻量级 Web 框架 Flask 的学习与实战,内容涵盖路由与视图、模板渲染、表单处理、数据库集成、用户认证以及RESTful API 开发。通过博客系统、任务管理工具与微服务接口等项目实战,帮助学员掌握 Flask 在快速构建小型到中型 Web 应用中的核心技能。

83

2025.08.25

Python Flask Web框架与API开发
Python Flask Web框架与API开发

本专题系统介绍 Python Flask Web框架的基础与进阶应用,包括Flask路由、请求与响应、模板渲染、表单处理、安全性加固、数据库集成(SQLAlchemy)、以及使用Flask构建 RESTful API 服务。通过多个实战项目,帮助学习者掌握使用 Flask 开发高效、可扩展的 Web 应用与 API。

64

2025.12.15

html版权符号
html版权符号

html版权符号是“©”,可以在html源文件中直接输入或者从word中复制粘贴过来,php中文网还为大家带来html的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

591

2023.06.14

html在线编辑器
html在线编辑器

html在线编辑器是用于在线编辑的工具,编辑的内容是基于HTML的文档。它经常被应用于留言板留言、论坛发贴、Blog编写日志或等需要用户输入普通HTML的地方,是Web应用的常用模块之一。php中文网为大家带来了html在线编辑器的相关教程、以及相关文章等内容,供大家免费下载使用。

638

2023.06.21

html网页制作
html网页制作

html网页制作是指使用超文本标记语言来设计和创建网页的过程,html是一种标记语言,它使用标记来描述文档结构和语义,并定义了网页中的各种元素和内容的呈现方式。本专题为大家提供html网页制作的相关的文章、下载、课程内容,供大家免费下载体验。

458

2023.07.31

html空格
html空格

html空格是一种用于在网页中添加间隔和对齐文本的特殊字符,被用于在网页中插入额外的空间,以改变元素之间的排列和对齐方式。本专题为大家提供html空格的相关的文章、下载、课程内容,供大家免费下载体验。

240

2023.08.01

html是什么
html是什么

HTML是一种标准标记语言,用于创建和呈现网页的结构和内容,是互联网发展的基石,为网页开发提供了丰富的功能和灵活性。本专题为大家提供html相关的各种文章、以及下载和课程。

2853

2023.08.11

html字体大小怎么设置
html字体大小怎么设置

在网页设计中,字体大小的选择是至关重要的。合理的字体大小不仅可以提升网页的可读性,还能够影响用户对网页整体布局的感知。php中文网将介绍一些常用的方法和技巧,帮助您在HTML中设置合适的字体大小。

500

2023.08.11

vlookup函数使用大全
vlookup函数使用大全

本专题整合了vlookup函数相关 教程,阅读专题下面的文章了解更多详细内容。

28

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.7万人学习

AngularJS教程
AngularJS教程

共24课时 | 2.2万人学习

CSS教程
CSS教程

共754课时 | 17.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号