如何:使用 Flask 在 WTForms 中动态生成 CSRF-Token [英] Howto: Dynamically generate CSRF-Token in WTForms with Flask

查看:41
本文介绍了如何:使用 Flask 在 WTForms 中动态生成 CSRF-Token的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个水果表单,其中有一个用于香蕉的 FieldList 对象:

I have a fruits form that has one FieldList object for the bananas:

bananas = FieldList(FormField(BananaForm))

在前端,最初,我将这些字段之一添加到 FieldList

In the frontend, initially, I add one of those fields to the FieldList

form.append_entry()

现在使用 Javascript 我设法创建函数,可以动态添加(加号按钮)或删除(减号按钮)可以填充信息的 BananaForm 字段的数量.

Now with Javascript I managed to create functions, that can dynamically add (plus button) or remove (minus button) the number of BananaForm fields that can be filled with information.

FielstList 自动为其所有字段创建 ID.所以为了用js做动态添加,我复制HTML代码并设置字段id += 1,如:

FielstList automatically creates ids for all of its fields. So to do dynamical adding with js, I duplicate the HTML code and set the field id += 1, like:

第一个字段:

<tr>
  <td><input id="bananas-0-originCountry" type="text" /></td>
</tr>

+= 1 的重复字段:

duplicated field with += 1:

<tr>
  <td><input id="bananas-1-originCountry" type="text" /></td>
</tr>

当我像这样相应地命名它们并提交表单时,WTForms 将自动识别后端中添加的字段(工作正常).

When I name them accordingly like this and submitting the form, WTForms will automatically recognize the added fields in the backend (works fine).

到目前为止一切顺利,但这是我的问题:为了使表单有效,我必须向每个 WTForm 添加 CSRF 字段.在 Jinja 模板中,我使用:

So far so good, but here is my problem: For a form to be valid, I have to add CSRF-fields to every WTForm. In the Jinja template I do this with:

{{ form.hidden_tag() }}

但是,当我只是用我的 js 函数复制 HTML 时,我缺少 CSRF 字段(因为在提交之前,后端表单对象不知道添加的 FormFields).那么如何动态生成这些 CSRF 字段呢?(Ajax 请求?如果是,怎么做?)

However, when I just copy the HTML with my js function, I'm missing the CSRF-fields (because until submitted, the backend form object doesn't know about the added FormFields). So how can I generate these CSRF-fields dynamically? (An Ajax Request? If yes, how?)

这应该是带有表单和烧瓶的标准用例.我希望我的描述是可以理解的,如果不是,请告诉我.任何帮助表示赞赏!

This should be a standard use case with forms and flask. I hope my description was understandable, if not please let me know. Any help appreciated!

更新:这是我的代码

JS 函数

function addBanana(){
    // clone and insert banana node
    var node = document.getElementById("fruitTable");
    var trs = node.getElementsByTagName("tr");
    var tr = trs[trs.length-2];
    var tr2 = tr.cloneNode(true);
    tr.parentNode.insertBefore(tr2, tr);

    // in order to increment label and input field ids
    function plusone(str){
        return str.replace(
            new RegExp("-(\d+)-", "gi"),
            function($0, $1){
                var i = parseInt($1) + 1;
                return "-" + i + "-";
            }
        );
    }

    // change inputs
    var inputs = tr.getElementsByTagName("input");

    for (var i = 0; i < inputs.length; i++){
        inputs[i].setAttribute("id", plusone(inputs[i].getAttribute("id")));
    }

    var minusbutton = 
        ['<td>',
        '<button class="btn" type="button" onClick="removeBanana()"><i class="icon-black icon-minus"></i></button>',
        '</td>'
        ].join('
');

    // only append at the first add
    // second add automatically copies minus button
    if (trs.length < 6){
        tr.innerHTML += minusbutton
    }
}

function removeBanana(){
    var node = document.getElementById("fruitTable");
    var trs = node.getElementsByTagName("tr");
    var tr = trs[trs.length-2];
    var trParent = tr.parentNode;
    trParent.removeChild(tr);
}

Jinja 模板:

<form method="POST" action="newsubmit">
  {{ form.hidden_tag() }}
  <table id="fruitTable" class="table">
    {{ render_field(form.description) }}
    <tr><td><h3>Bananas</h3></td></tr>
    {% set counter = 0 %}
    {% for banana in form.bananas %} 
      <tr>
        {{ banana.hidden_tag() }}
        {% set counter = counter + 1%}
        {% for field in banana if field.widget.input_type != 'hidden' %}
          {{ render_field_oneline(field) }}
        {% endfor %}
        {% if counter > 1 %} 
          <td>
            <button class="btn" type="button" onClick="removeBanana()"><i class="icon-black icon-minus"></i></button>
          </td>
        {% endif  %} 
      </tr>
    {% endfor %}
      <tr><td></td><td><button class="btn" type="button" onClick="addBanana()"><i class="icon-black icon-plus"></i></button></td></tr>
  </table>
<input class="btn btn-primary" style="margin-left:300px;"type="submit" value="Submit" />
</form>

Jinja 模板宏:

{% macro render_field_oneline(field) %}
<td>{{ field.label }}</td>
<td>{{ field(**kwargs)|safe }}
  {% if field.errors %}
  <ul class=errors>
    {% for error in field.errors %}
    <li>{{ error }}</li>
    {% endfor %}
  </ul>
  {% endif %}
</td>
{% endmacro %}

{% macro render_field(field) %}
<tr>
  {{ render_field_oneline(field) }} 
</tr>
{% endmacro %}

推荐答案

我发现了它的工作原理:

I discovered how it works:

CSRF-Tag 可以简单地复制.id 必须相应地更改和递增,但哈希值可能保持不变.

The CSRF-Tag can simply be copied. The id must be changed and incremented accordingly, but the hash may stay the same.

我认为不可能有许多具有相同 CSRF-Tag 哈希的字段,但实际上确实如此!

I didn't think it was possible to have many Fields with the same CSRF-Tag hash, but it actually does!

这篇关于如何:使用 Flask 在 WTForms 中动态生成 CSRF-Token的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆