官方文档: http://www.pythondoc.com/flask-wtf/csrf.html#id4
根据 csrf_token 校验原理,具体操作步骤有以下几步:
为了能够让所有的视图函数受到 CSRF 保护,你需要开启 CsrfProtect 模块:
from flask_wtf.csrf import CsrfProtect
CsrfProtect(app)
像任何其它的 Flask 扩展一样,你可以惰性加载它:
from flask_wtf.csrf import CsrfProtect
csrf = CsrfProtect()
def create_app():
app = Flask(__name__)
csrf.init_app(app)
前端表单提交代码:
如果模板中存在表单,
<form method="post" action="/">
{{ form.csrf_token }}
form>
但是如果模板中没有表单,你仍然需要一个 CSRF 令牌:
<form method="post" action="/">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
form>
无论何时未通过 CSRF 验证,都会返回 400 响应。你可以自定义这个错误响应:
@csrf.error_handler
def csrf_error(reason):
return render_template('csrf_error.html', reason=reason), 400
你也可以在所有的视图中禁用 CSRF 保护,通过设置 WTF_CSRF_CHECK_DEFAULT 为 False,仅当你需要的时候选择调用 csrf.protect()。
@app.before_request
def check_csrf():
if not is_oauth(request):
csrf.protect()
当设置对所有视图启动CSRF保护时,也可以让某些视图函数关闭csrf保护
@csrf.exempt
@app.route('/foo', methods=('GET', 'POST'))
def my_handler():
# ...
return 'ok'
不需要表单,通过 AJAX 发送 POST 请求成为可能。Flask0.9.0 版本后这个功能变成可用的。
我们推荐的方式是在 meta 标签中渲染 CSRF 令牌:
<meta name="csrf-token" content="{{ csrf_token() }}">
在 script 标签中渲染同样可行:
<script type="text/javascript">
var csrftoken = "{{ csrf_token() }}"
script>
下面的例子采用了在 meta标签渲染的方式, 在 script 中渲染会更简单,你无须担心没有相应的例子。
无论何时你发送 AJAX POST 请求,为其添加 X-CSRFToken 头:
var csrftoken = $('meta[name=csrf-token]').attr('content')
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
})
当你定义你的表单的时候,如果犯了这个错误 : 从 wtforms 中导入 Form 而不是从 flask.ext.wtf 中导入,CSRF 保护的大部分功能都能工作(除了 form.validate_on_submit()),但是 CSRF 保护将会发生异常。在提交表单的时候,你将会得到 Bad Request/CSRF token missing or incorrect 错误。这个错误的出现就是因为你的导入错误,而不是你的配置问题。
我们需要生成token值并利用请求钩子设置cookie,然后前端就能获取到cookie里面的csrf_token:
from flask_wtf.csrf import generate_csrf
@app.after_request
def after_request(response):
# 调用函数生成csrf token
csrf_token = generate_csrf()
# 设置cookie传给前端
response.set_cookie('csrf_token', csrf_token)
return response
$.ajax({
...
headers: {"X-CSRFToken": getCookie("csrf_token")},
...
})
function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined;
}
下载包:
pip install flask-cors
官方文档:http://flask-cors.readthedocs.io/en/latest/
例子:
from flask_cors import CORS
app = Flask(__name__)
# r'/*' 是通配符,让本服务器所有的URL 都允许跨域请求
CORS(app, supports_credentials=True, resources=r'/*')