Flask和Ajax Post请求400

wir*_*bel 17 javascript python ajax jquery flask

我正在编写一个基于小瓶子的站点,我想使用Ajax将数据从客户端发送到服务器.到目前为止,我只使用Ajax请求从服务器检索数据.这次我想通过POST请求提交数据.

这是烧瓶侧的接收器,我将其减少到几乎没有记录消息,以避免在此路由的实现中出现任何不必要的错误:

@app.route("/json_submit", methods=["POST"])
def submit_handler():
    # a = request.get_json(force=True)
    app.logger.log("json_submit")
    return {}
Run Code Online (Sandbox Code Playgroud)

提交ajax请求时,flask会给我400错误

127.0.0.1 - - [03/Apr/2014 09:18:50] "POST /json_submit HTTP/1.1" 400 -
Run Code Online (Sandbox Code Playgroud)

我也可以在浏览器的Web开发人员控制台中看到这一点

为什么烧瓶没有submit_handler使用请求中提供的数据进行调用?

 var request = $.ajax({
    url: "/json_submit",
    type: "POST",
    data: {
      id: id, 
      known: is_known
    },  
    dataType: "json",
  })  
   .done( function (request) {
  })
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 27

如果您正在使用Flask-WTF CSRF保护,则您需要在您的AJAX POST请求中免除您的视图或包含CSRF令牌.

豁免是由装饰者完成的:

@csrf.exempt
@app.route("/json_submit", methods=["POST"])
def submit_handler():
    # a = request.get_json(force=True)
    app.logger.log("json_submit")
    return {}
Run Code Online (Sandbox Code Playgroud)

要在AJAX请求中包含令牌,请将令牌插入页面中的某个位置; 在<meta>标头或生成的JavaScript中,然后设置X-CSRFToken标头.使用jQuery时,请使用ajaxSetup钩子.

使用元标记的示例(来自Flask-WTF CSRF文档):

<meta name="csrf-token" content="{{ csrf_token() }}">
Run Code Online (Sandbox Code Playgroud)

并在你的JS代码中的某个地方:

var csrftoken = $('meta[name=csrf-token]').attr('content')

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken)
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

你的处理程序实际上并没有发布JSON数据; 它仍然是一个常规的url编码POST(数据最终将在request.formFlask端); 您必须将AJAX内容类型设置为application/json并用于JSON.stringify()实际提交JSON:

var request = $.ajax({
   url: "/json_submit",
   type: "POST",
   contentType: "application/json",
   data: JSON.stringify({
     id: id, 
     known: is_known
   }),  
})  
  .done( function (request) {
})
Run Code Online (Sandbox Code Playgroud)

现在可以使用该request.get_json()方法将数据作为Python结构进行访问.

dataType: "json",对参数$.ajax时,你的看法是只需要返回 JSON(例如,你使用flask.json.jsonify()产生JSON响应).它让jQuery知道如何处理响应.

  • 您好,您实际上不需要将csrf设置为元标记。只需在您的javascript中设置以下变量即可:var csrftoken =“ {{csrf_token()}}”; 顺便说一句,不要豁免您的路线令牌!否则,csrf保护是无用的...希望对您有所帮助。如果需要,我可以编辑答案。 (2认同)
  • @pierrelb:我通常将* static *文件用于JS代码(以便可以将其长期缓存在浏览器中),然后在动态页面中使用meta标记或`data`属性是更具可扩展性的选项。答案*确实*在生成的JavaScript *中包含短语*或。而且我还明确指出,豁免是在X-CSRFToken` HTTP标头中设置令牌的“替代方案”。 (2认同)
  • @deesolie:CSRF 保护不适用于 GET、HEAD、OPTIONS 或 TRACE 请求,因此测试避免将标头添加到这些请求中。将其视为一种节省带宽的措施。您可以反转测试,并[匹配您的 Flask-WTF 配置 `WTF_CSRF_METHODS` 选项](https://flask-wtf.readthedocs.io/en/latest/config.html#configuration)。 (2认同)