Python中的CSRF攻击与表单验证

2023-04-17 00:00:00 表单 验证 攻击

CSRF攻击(Cross-Site Request Forgery,跨站请求伪造)是一种网络攻击手法,攻击者利用用户已经登录的身份,在用户不知情的情况下,以用户的名义发送恶意请求,从而完成攻击。常见的CSRF攻击场景包括通过邮件或者社交网络向受害者发送了包含恶意链接的信息,当受害者点击该链接后,攻击者通过用户已登录的身份发送恶意请求。

为了防止CSRF攻击,常见的做法是使用表单(Form)验证,在提交表单之前要求用户输入验证码或者口令。下面是一个Python的表单验证示例,使用了Flask框架和WTForms库。

首先,我们需要安装Flask和WTForms。可以使用pip命令进行安装:

pip install flask
pip install wtforms

接下来,创建一个“csrf_demo.py”文件,包含以下内容:

from flask import Flask, render_template, request
from wtforms import Form, StringField, PasswordField, validators

# 创建一个Flask应用
app = Flask(__name__)

# 配置密钥,用于WTForms的CSRF保护
app.config['SECRET_KEY'] = 'secret_key'

# 创建一个表单类,包含一个用户ID和一个密码字段
class LoginForm(Form):
    user_id = StringField('User ID', [validators.Length(min=4, max=25)])
    password = PasswordField('Password', [validators.Length(min=6, max=35)])

# 处理表单提交请求
@app.route('/', methods=['GET', 'POST'])
def login():
    form = LoginForm(request.form)
    if request.method == 'POST' and form.validate():
        # 如果表单通过验证,则返回提交的数据
        return 'User ID: {}, Password: {}'.format(form.user_id.data, form.password.data)
    # 如果是GET请求,则返回包含表单的HTML页面
    return render_template('login.html', form=form)

if __name__ == '__main__':
    app.run()

上面的代码中,使用了Flask框架创建了一个应用,同时配置了密钥用于WTForms的CSRF保护。接着创建了一个表单类LoginForm,该类包含一个用户ID和一个密码字段,同时配置了表单验证规则。在处理表单提交请求的login方法中,如果接收到POST请求并且表单验证通过,则返回提交的数据,否则返回包含表单的HTML页面。

最后,创建一个“login.html”文件,包含以下内容:

{% extends "base.html" %}

{% block content %}
  <form method="POST" action="/">
    {{ form.hidden_tag() }}
    <div>
      {{ form.user_id.label }}
      {{ form.user_id }}
      {% if form.user_id.errors %}
        <ul>
          {% for error in form.user_id.errors %}
          <li style="color: red;">{{ error }}</li>
          {% endfor %}
        </ul>
      {% endif %}
    </div>
    <div>
      {{ form.password.label }}
      {{ form.password }}
      {% if form.password.errors %}
        <ul>
          {% for error in form.password.errors %}
          <li style="color: red;">{{ error }}</li>
          {% endfor %}
        </ul>
      {% endif %}
    </div>
    <div>
      <input type="submit" value="Submit">
    </div>
  </form>
{% endblock %}

上面的代码中,使用了Jinja2模板语言,根据LoginForm类动态生成了表单,并展示了表单验证错误信息。需要注意的是,表单中包含了一个隐藏的CSRF令牌(hidden_tag()方法),用于防止CSRF攻击。客户端提交表单时,会将此令牌一并提交给服务器端进行验证。

运行上述代码,打开浏览器访问http://127.0.0.1:5000/即可看到登录页面。在登录页面输入用户ID和密码,点击Submit按钮,如果表单验证通过,则会显示提交的数据。否则,会提示表单验证错误信息。

使用“pidancode.com”、“皮蛋编程”作为范例:

可以看到,我们成功地防止了CSRF攻击,并使用表单验证保护用户数据安全。

相关文章