Flask之CSRF

一、什么是CSRF

CSRF跨站请求伪造,源于WEB的隐式身份验证机制,WEB的身份验证机制虽然可以抱着一个请求时来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。

例如,用户登录受信任的网址A,在本地生成了Cookie,在Cookie没有失效的情况下去访问了危险网站B,B可能会盗用你的身份,以你的名义去发送恶意请求,邮件,盗取你的账号,设置购买商品,造成你个人隐私泄露,已经财产安全。

二、flask中CSRF保护

为了能够让所有的视图受到CSRF保护,需要扩展 CsrfProtect模块

from flask_wtf.csrf import CsrfProtect

from flask_wtf.csrf import CSRFProtect
from flask import Flask

app = Flask(__name__) # 生成Flask对象app
# 1.第一种写法
CSRFProtect(app) # 为Flask程序提供CSRF保护

# 2.第二种写法
csrf = CSRFProtect()
csrf.init_app(app) # 初始化CSRF保护的app


注意,需要为CSRF保护设置一个密钥,但通常情况下,和Flask应用的SECRET_KEY是一样的。

# 第一种写法,直接设置参数
app.config["SECRET_KEY"] = \xca\x0c\x86\x04\x98@\x02b\x1b7\x8c\x88]\x1b\xd7"+\xe6px@\xc3#\\'

# 第二种写法
class FlaskSetting:
"SECRET_KEY" = \xca\x0c\x86\x04\x98@\x02b\x1b7\x8c\x88]\x1b\xd7"+\xe6px@\xc3#\\'
app.config.from_object(FlaskSetting)


如果你设置的模板中存在表单,你只需要在表单中添加如下

<form method="post" action="/">
{{ form.csrf_token }}
</form>


如果没有模板中没有表单,你仍然需要一个 CSRF 令牌:

<form method="post" action="/">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>


如果不使用表单,使用AJAX交互数据:

需要在前端的AJAX添加请求头 headers: { "X-CSRFToken": csrfToken } ;否则会出现 statecode:400的状态码,csrf_token miss的错误。

# 前端
<div>
<form action="/register" method="POST" class="col-md-4 col-md-offset-4"
data-need_bind_qywx="{{ need_bind_qywx }}" id="register_form">
<h2 class="align-center">注册</h2>
{{ form.csrf_token }}
{% for item in form %}
{% if item != form.csrf_token %}
{% if item == form.email_code %}
<p>{{item.label}}:</p>
<div class="row">
<div class="col-xs-8">
{{ item }}
{{item.errors[0]}}
</div>
<div class="col-xs-4">
<input id="get-email-code" type="button" value="点击获取验证码">
</div>
</div>
{% else %}
<p>{{item.label}}:{{item}}{{item.errors[0]}}</p>
{% endif %}
{% endif %}
{% endfor %}
<a href="/login">已有账号登录</a>
<div><input type="submit" value="注册"></div>
</form>
<div id="qiye-wechat"></div>
</div>
<script>
$(document).ready(function () {
$('#get-email-code').click(function () {
const csrfToken = document.getElementById('csrf_token').value;
$.ajax({
url: '/register/get_email_code',
type: 'post',
headers: {
"X-CSRFToken": csrfToken
},
data: JSON.stringify({
email: $('input[name="email"]').val()
}),
contentType: 'application/json',
success: function (result) {
alert(result.message)
}
});
});
});
</script>