zoukankan      html  css  js  c++  java
  • flask——CSRFToken保护

    flask总结05(在 Flask 项目中解决 CSRF 攻击)

     

    一:安装 flask_wtf

    pip install flask_wtf

    二:设置应用程序的 secret_key,用于加密生成的 csrf_token 的值

    # session加密的时候已经配置过了.如果没有在配置项中设置,则如下:
    app.secret_key = "#此处可以写随机字符串#"

    三:导入 flask_wtf.csrf 中的 CSRFProtect 类,进行初始化,并在初始化的时候关联 app

    from flask.ext.wtf import CSRFProtect
    CSRFProtect(app)

    四:在表单中使用 CSRF 令牌:

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

    五:scrf的过程理解

    代码显示方法不被允许的代码

    #manage.py

    from flask import Flask, render_template, request, g
    from settings.dev import DevConfig
    from flask.ext.wtf import CSRFProtect
    
    app = Flask(__name__, template_folder="templates", static_folder="static")
    app.config.from_object(DevConfig)
    
    CSRFProtect(app)
    
    # @app.route("/csrf_test", methods=["get", "post"])
    @app.route("/csrf_test")
    def index():
        if request.method == "GET":
            return render_template("form.html")
    
        else:
            print(request.form)
    
            return "ok"
    
    if __name__ == "__main__":
        app.run()

    templates下的form.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>csrf案例</title>
    </head>
    <body>
        <form action="" method="post">
            账号:<input type="text" name="username"><br><br>
            密码:<input type="password" name="password"><br><br>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

    运行后显示的结果是:

    然后修改manage.py中的代码,添加

    @app.route("/csrf_test", methods=["get", "post"])

    代码如下:

    from flask import Flask, render_template, request, g
    from settings.dev import DevConfig
    from flask.ext.wtf import CSRFProtect
    
    app = Flask(__name__, template_folder="templates", static_folder="static")
    app.config.from_object(DevConfig)
    
    CSRFProtect(app)
    
    @app.route("/csrf_test", methods=["get", "post"])
    def index():
        if request.method == "GET":
            return render_template("form.html")
    
        else:
            print(request.form)
    
            return "ok"
    
    if __name__ == "__main__":
        app.run()

    再次执行:并且提交:

    说明需要在html文档中添加:csrf_token

    <input type="hidden" name="csrf_token" value="{{csrf_token()}}">

    修改后的代码是:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>csrf案例</title>
    </head>
    <body>
        <form action="" method="post">
            <input type="hidden" name="csrf_token" value="{{csrf_token()}}">
            账号:<input type="text" name="username"><br><br>
            密码:<input type="password" name="password"><br><br>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

    运行后的结果显示:

    flask——CSRFToken保护

    根据 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_token 的值

    # 导入生成 csrf_token 值的函数
    from flask_wtf.csrf import generate_csrf
    # 调用函数生成 csrf_token
    csrf_token = generate_csrf()

    将 csrf_token 的值传给前端浏览器
    实现思路:可以在请求勾子函数中完成此逻辑

    @app.after_request
    def after_request(response):
        # 调用函数生成 csrf_token
        csrf_token = generate_csrf()
        # 通过 cookie 将值传给前端
        response.set_cookie("csrf_token", csrf_token)
        return response

    在前端请求时带上 csrf_token 值
    根据登录和注册的业务逻辑,当前采用的是 ajax 请求
    所以在提交登录或者注册请求时,需要在请求头中添加 X-CSRFToken 的键值对

    $.ajax({
        url:"/passport/register",
        type: "post",
        headers: {
            "X-CSRFToken": getCookie("csrf_token")#get_Cookie为自定义函数
        },
        data: JSON.stringify(params),
        contentType: "application/json",
        success: function (resp) {
            if (resp.errno == "0"){
                // 刷新当前界面
            location.reload()
            }else {
                $("#register-password-err").html(resp.errmsg)
                $("#register-password-err").show()
            }
        }
    })

    flask csrf保护的使用技巧

    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。 ——百度百科

    网上关于csrf攻击的一个最典型的例子是银行通过url+参数转钱的问题,很好理解。

    flask 作为一个强带的web微框架,自然也是支持防范csrf攻击的。

    通过Flask-WTF来保护表单免受CSRF攻击
    何为Flask-WTF
    简单说来,使用它可以方便我们构建表单和验证表单,具体用法这里不做赘述

    怎么开启保护?
    极少的配置,一个应用令牌:

    app.config['SECRET_KEY'] = 'you can't know'
    或csrf专用令牌
    app.config['WTF_CSRF_SECRET_KEY'] = 'IT 666 to 709 kill pic'

    Flask-WTF默认是开启CSRF保护的,你需要的做的是在你的模板中表单一栏加入:

    {{ form.csrf_token }}
    或者
    {{ form.hidden_tag() }}

    这样,csrf保护已经开启。如若你没有上面的代码,提交表单会无法通过form.validate_on_submit(),错误为

    {'csrf_token': ['The CSRF token is missing.']},但这并不会导致http错误,仅是无法通过验证。

    关闭保护
    自然,我们很可能有的表单不需要保护,那么,以下三种:

    全局禁用:app.config中设置WTF_CSRF_ENABLED = False
    单个表单禁用:生成表单时加入参数form = Form(csrf_enabled=False)
    不使用Flask-WTF…啊啊,这个很好理解

    http://docs.jinkan.org/docs/flask-wtf/from.html

    flask 内置的保护机制

    有些时候,我根本就用不到Flask-WTF,那么我可以使用flask自身提供的保护机制。

    开启保护

    要开启csrf攻击保护,需要一下几个步骤。

    from flask_wtf.csrf import CSRFProtect
    
    app.config['SECRET_KEY'] = 'you never guess'
    CSRFProtect(app)
    主要为:导入方法,设置密钥,进行保护。
    这时候对于一个普通的form,如果你没有
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />

    flask会抛出http错误。

    临时关闭保护

    那么,如何临时关闭csrf保护呢。
    上面的代码做修改:

    去掉 CSRFProtect(app)
    改为 csrf = CSRFProtect()
    
    if __name__ == '__main__':中加入
    csrf.init_app(app)
    
    在不需要保护的路由上当加上:
    @csrf.exempt

    如此,临时关闭了csrf。

    http://docs.jinkan.org/docs/flask-wtf/csrf.html



  • 相关阅读:
    web之用FileUpload上传文件
    利用LinQ技术和lambd表达式进行增删改查
    weibform中Application、ViewState对象和分页
    webform中Session和Cookies对象的用法、登录保持
    点击input框弹出输入法 ,底部footer内容就会被顶上去的问题
    实现input密码框显示/隐藏的功能
    Elasticsearch 入门
    svn 提示错误 :Failed to run the WC DB work queue associated with 解决办法
    provider:命名管道提供程序,error:40
    ECMAScript (Javascript)位运算符
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/11770647.html
Copyright © 2011-2022 走看看