10.新闻项目——插曲——处理CSRF

思路讲解

在前面,为了解决程序的保存问题,我们把csrf的保护关掉了,现在,注册与登陆的逻辑完成了,我们来解决这个小麻烦。

这里,我们要注意,这个表单不是我们完成的,而是前端写好的,所以我们要做的就是不使用FlaskForm来实现CSRF保护,

之前完成csrf保护的时候是在cookie和表单中都加入了一个csrf_token,然后当浏览器携带两个内容来的时候进行比较。而现在我们没有办法在在表单中加入csrf_token,第一是因为表单不是我们写的,第二个是因为有的请求只是一个ajax,它并没有办法像表单一样提交空白的标签。所以我们得想个其他办法,看源码(CTRL加左键点CSRFProtect):

 当我们查看源码时发现,第一个框时需要csrf验证的请求方式,而第二个框中放入,是验证时会从请求头中获取的数据,这里会从两种请求头中获取,选择一个即可。

我们再看一下后面的源码:

在验证之前,用到了一个东西,叫做钩子,关于钩子的相关内容,我们在学习Flask基础的时候介绍过,这个before_request表示,在请求来了视图函数处理之前要执行的函数。

现在,线索已经找的差不多了,我们可以去处理这个东西了。

所以安装之前所说的内容,我们需要按照步骤完成下面内容:

1.开启CSRF的验证

2.生成csrf_token值

3.写入到浏览器的cookie

4.手动读取浏览器的cookie中的csrf_token值,写入到请求头当中headers[‘X-CSRFToken/X-CSRF-Token’] = ‘csrf_token’

 

代码实现

1.开启CSRF的验证

开启CSRF验证

info -> __init__.py

 

 

2.生成csrf_token值并放入cookie中

这里我们需要将生成的csrf_token写入到浏览器的cookie中,所以也可以利用钩子,在每次请求之后,向cookie中写入csrf_token。

from flask_wtf.csrf import generate_csrf

    ....

def create_app(config_name):
    """创建app的工厂方法
    参数:根据参数选择不同的配置类
    """

    ....

    # 开启CSRF保护:因为项目中的表单不再使用FlaskForm来实现,所以不会自动地开启CSRF保护,需要我们自己开启
    CSRFProtect(app)

    # 使用请求勾子,实现每个响应中写入cookie
    @app.after_request
    def setup_csrftoken(response):
        # 生成csrf_token的值,生成csrf_token的函数直接调用就可以了
        csrf_token = generate_csrf()

        # 将csrf_token的值写入到cookie
        response.set_cookie('csrf_token', csrf_token)
        return response

    # 指定session存储在后端的位置
    Session(app)


    .....

 当我们再次访问的时候,就会发现cookie中多了一个csrf_token的键值对。

而在ajax中加入框中的内容,则代表在请求的request请求头中,设置X-CSRFToken,而它的值则是使用函数来获取到的cookie值。

 

 我们可以将这部分拷贝下来,在post请求的时候用到就加上(利用查询去找post会方便些)。

总体说明:

1.在客户端向后端请求界面数据的时候,后端会往响应中的 cookie 中设置 csrf_token 的值
2.给post请求的ajax中的headers添加“X-CSRFToken”,添加值也是 csrf_token
3.在用户发起请求以后,会带上这两个值向后台发起请求
4.后端接受到请求,会做以下几件事:
1.从 cookie中取出 csrf_token
2.从headers中取出csrf_token
3.CSRFProtect会为我们自动比较这两个值
如果比较之后两值一样,那么代表是正常的请求,如果没取到或者比较不一样,代表不是正常的请求,不执行下一步操作
另外不要担心黑客能拿到csrf_token值,由于同源策略, 黑客是没办法获取用户浏览器中的csrf_token隐藏域,由于浏览器安全机制,黑客也没办法获取cookie中的csrf_token。

posted @ 2019-11-20 15:59  苦行僧95  阅读(125)  评论(0编辑  收藏  举报