Flask Wtf是一个flask的表单插件,主要提供表单后台验证功能并自动为表单附加crsf_token的功能,其还有一个功能便是为所有视图提供crsf验证,通过附加在模板的{crsf_token()}渲染来获得crsf_token,以便网页的Ajax添加X-CSRFToken消息头的填充。
文章着重讲讲crsf_token的功能,crsf_token可以有效的防止csrf的攻击,当用户被诱导进入钓鱼网站并且进行表单的提交时,由于钓鱼网站拿不到用户的crsf_token从而提交无效。
表单的crsf_token功能的实现:为所有的form添加一个crsf_token的隐藏值(FlaskForm继承SecureForm,SecureForm中添加的crsf_token,通过CSRFTokenField以及HiddenField实现),从而携带至网页的Form表单中,SecureForm中代码如下:
self.csrf_token.current_token = self.generate_csrf_token(csrf_context)
其中generate_csrf_token被FlaskForm改写了。
网页的crsf_token需要用到Flask_Wtf的CsrfProtect并init_app之后方可生效,其核心方式如下:
@app.context_processord
def csrf_token():
@app.before_request
def _csrf_protect():
看完源码都很好理解,需要注意的是crsf_token都会保存在session[token_key]中发送给发送给客户端的cookie中,这样返回的crsf_token不但会验证真伪(SECRET_KEY)和过期时间,还会与解cookie获得的session[token_key]进行比较,这带来一个好处:在用户登录的过程中,可以通过这个crsf_token做一个防重放攻击。因为每次网页都要携带crsf_token并且用完就扔,监听者抓到登录密码密文和crsf_token时,crsf_token已经过期,重放无效。
目前还有一个疑问,当网页设置了crsf_token保护,而且网页中存在表单时,crsf_token是否会算两次?如果又同时存在多个表单,那会不会算很多次?不过多算几次除了浪费资源倒不会有什么大问题。