首页 > 解决方案 > Python Flask CSRF 令牌给出了意想不到的结果

问题描述

我正在尝试实现 csrf,但我对它的工作原理感到困惑。我的python文件。

from flask_wtf.csrf import CSRFProtect, CSRFError
csrf = CSRFProtect()
app = Flask(__name__)
app.config['SECRET_KEY'] = 'FlaskAppKey'
csrf.init_app(app)

我的 .js 文件。

       var csrftoken = "{{ csrf_token () }}";
       $.ajax(
       {
    url: '/calendar_data/',
    dataType:'json',
    type: 'GET',
    contentType: 'application/json',
    data:dataString,
    beforeSend:function(xhr,settings)
    {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
        },

request.header转储显示。

X-Csrftoken: IjQ5NjYxOWRiYzgwOWU1N2Q0OWY0MmUxMDRjOGU1ZDcwNGUwNTJkM

如果我删除令牌,则站点不会出错。

我有一条错误路线。所以我不确定我是否正确实施了一切。从代码中删除令牌后,我期待一个错误。

      @app.errorhandler(CSRFError)
      def handle_csrf_error(e):
  print(e)
  return ''

如果未发送令牌,则请求错误不应该吗?

路线页面

@app.route("/calendar_data/")
def calendar_data():
    stuff
return jsonify(data=data[1])

标签: pythonpython-3.xflaskflask-wtforms

解决方案


您可能希望使用POST请求进行测试。

这可能不会直接回答您的问题,而是引导您走向 WTF-Forms 行为。您是否尝试过发送POST请求而不是GET请求?我问的原因是因为通常保护措施是防止数据插入,特别是在请求中(有关此线程POST的更多信息。

此外,根据文档,您可以将beforeSendajax 方法设置为以下内容:

 var csrf_token = "{{ csrf_token() }}";

    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrf_token);
            }
        }
    });

## this should also technically exclude the CSRF token from the header

如果您确实尝试了POST请求,请确保在您的路线上接受它:

@app.route("/calendar_data/", methods=('GET', 'POST'))
def calendar_data():
    if request.method == 'POST':
        print ('posted')
    stuff
return jsonify(data=data[1])

据我了解,如果您不将 CSRF 令牌传递给 POST 请求,或者它的格式不正确,那么这种情况将不起作用。

GET 请求中有关 CSRF 的更多信息

根据CSRF 安全令牌的这份备忘单:

理想的解决方案是仅在 POST 请求中包含 CSRF 令牌,并修改具有状态更改影响的服务器端操作以仅响应 POST 请求。这实际上是 RFC 2616 对 GET 请求的要求。如果保证敏感的服务器端操作只响应 POST 请求,则无需在 GET 请求中包含令牌。

此外,根据rfc7231

如果请求方法定义的语义本质上是只读的,则请求方法被认为是“安全的”

在本规范定义的请求方法中,GET、HEAD、OPTIONS 和 TRACE 方法被定义为安全的。


推荐阅读