Flask框架 CSRF 保护实现方法详解
本文实例讲述了Flask框架CSRF保护实现方法。分享给大家供大家参考,具体如下:
FlaskCSRF保护
- 为什么需要CSRF?
- 具体操作步骤
- 实现
- 后端书写
- 在表单添加保护
- 自定义错误响应和关闭保护
- ajax提交数据
- 故障排除
为什么需要CSRF?
Flask-WTF表单保护你免受CSRF威胁,你不需要有任何担心。尽管如此,如果你有不包含表单的视图,那么它们仍需要保护。
例如,由AJAX发送的POST请求,然而它背后并没有表单。在Flask-WTF0.9.0以前的版本你无法获得CSRF令牌。这是为什么我们要实现CSRF。
具体操作步骤
根据csrf_token校验原理,具体操作步骤有以下几步:
1.后端生成csrf_token的值,在前端请求登录或者注册界面的时候将值传给前端,传给前端的方式可能有以下两种:
在模板中的From表单中添加隐藏字段
将csrf_token使用cookie的方式传给前端
2.在前端发起请求时,在表单或者在请求头中带上指定的csrf_token
3.后端在接受到请求之后,取到前端发送过来的csrf_token,与第1步生成的csrf_token的值进行校验
4.如果校验对csrf_token一致,则代表是正常的请求,否则可能是伪造请求,不予通过
而在Flask中,CSRFProtect这个类专门只对指定app进行csrf_token校验操作,所以开发者需要做以下几件事情:
生成csrf_token的值
将csrf_token的值传给前端浏览器
在前端请求时带上csrf_token值
实现
后端书写
为了能够让所有的视图函数受到CSRF保护,你需要开启CsrfProtect模块:
fromflask_wtf.csrfimportCsrfProtect CsrfProtect(app)
像任何其它的Flask扩展一样,你可以惰性加载它:
fromflask_wtf.csrfimportCsrfProtect csrf=CsrfProtect() defcreate_app(): app=Flask(__name__) csrf.init_app(app)
Note
你需要为CSRF保护设置一个秘钥。通常下,同Flask应用的SECRET_KEY是一样的。
在表单添加保护
如果模板中存在表单,你不需要做任何事情。与之前一样:
{{form.csrf_token}}
但是如果模板中没有表单,你需要一个CSRF令牌:
自定义错误响应和关闭保护
无论何时未通过CSRF验证,都会返回400响应。你可以自定义这个错误响应:
@csrf.error_handler defcsrf_error(reason): returnrender_template('csrf_error.html',reason=reason),400
我们强烈建议你对所有视图启用CSRF保护。但也提供了某些视图函数不需要保护的装饰器:
@csrf.exempt @app.route('/foo',methods=('GET','POST')) defmy_handler(): #... return'ok'
默认情况下你也可以在所有的视图中禁用CSRF保护,通过设置WTF_CSRF_CHECK_DEFAULT为False,仅仅当你需要的时候选择调用csrf.protect()。这也能够让你在检查CSRF令牌前做一些预先处理:
@app.before_request defcheck_csrf(): ifnotis_oauth(request): csrf.protect()
ajax提交数据
不需要表单,通过AJAX发送POST请求成为可能。Flask0.9.0版本后这个功能变成可用的。
- 假设你已经使用了CsrfProtect(app),你可以通过{{csrf_token()}}获取CSRF
令牌。这个方法在每个模板中都可以使用,你并不需要担心在没有表单时如何渲染CSRF令牌字段。
我们推荐的方式是在meta标签中渲染CSRF令牌:
在script标签中渲染同样可行:
varcsrftoken="{{csrf_token()}}"
下面的例子采用了在meta标签渲染的方式,在script中渲染会更简单,你无须担心没有相应的例子。
无论何时你发送AJAXPOST请求,为其添加X-CSRFToken头:
varcsrftoken=$(‘meta[name=csrf-token]').attr(‘content') KaTeXparseerror:Expected'}',got'EOF'atendofinput:…|OPTIONS|TRACE)/i.test(settings.type)&&!this.crossDomain){ xhr.setRequestHeader(“X-CSRFToken”,csrftoken) } } })
或者这么写ajax:
在提交请求时,需要在请求头中添加X-CSRFToken的键值对
$.ajax({ ... headers:{ "X-CSRFToken":getCookie("csrf_token") }, ... })
故障排除
当你定义你的表单的时候,如果犯了这个错误:从wtforms中导入Form而不是从flask.ext.wtf中导入,CSRF保护的大部分功能都能工作(除了form.validate_on_submit()),但是CSRF保护将会发生异常。在提交表单的时候,你将会得到BadRequest/CSRFtokenmissingorincorrect错误。这个错误的出现就是因为你的导入错误,而不是你的配置问题。
希望本文所述对大家基于flask框架的Python程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。