【问题标题】:WTForms FormField causing csrf_token errorsWTForms FormField 导致 csrf_token 错误
【发布时间】:2020-10-03 22:38:44
【问题描述】:

我有一个烧瓶项目,它基本上有 2 个表单类,它们充当第三个表单类中的子表单。我将 2 个子表单与 FormField 字段一起使用。问题是当我提交表单时,我收到两个子表单的 csrf_token 错误。如果我在子表单中使用 csrf=false 属性,我不会得到这个,但这是否意味着我现在对 CSRF 攻击持开放态度?

class AddressForm(FlaskForm):

    address = StringField(label='Address', validators=[DataRequired()])
    address2 = StringField(label='Address 2', validators=[Optional()])
    city = StringField(label='City', validators=[DataRequired()])
    county = SelectField(label='County', validators=[DataRequired()], choices=[], coerce=int)

    class Meta:
        csrf = False


class NameForm(FlaskForm):
    first_name = StringField(label='First Name', validators=[DataRequired(), Length(min=2)] )
    last_name = StringField(label='Last Name', validators=[DataRequired(), Length(min=2)] )

    class Meta:
        csrf = False

class OrderForm(FlaskForm):

    # Customer Details
    customer_name = FormField(NameForm, separator='_')
    customer_email = EmailField(label='Email', validators=[DataRequired(), Email()])
    customer_mobile_phone = StringField(label='Mobile Phone Number', validators=[DataRequired()])
    customer_alternative_phone = StringField(label='Alternative Phone Number', validators=[Optional()])
    # Delivery Details
    delivery_address = FormField(AddressForm, separator='_')
    area = SelectField(label='Area', validators=[DataRequired()], coerce=int)

我已经在表单中包含了{{ form.hidden_tag() }},并且还配置了一个 SECRET_KEY。

【问题讨论】:

    标签: python flask csrf flask-wtforms


    【解决方案1】:

    您在表单标签中包含 {{ form.csrf_token }} 以使用 CSRF 保护。 Per the documentation,

    使用 FlaskForm 时,像平常一样渲染表单的 CSRF 字段。

    <form method="post">
        {{ form.csrf_token }}
    </form>
    

    如果模板不使用 FlaskForm,则使用表单中的标记呈现隐藏输入。

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

    您可能会发现参考一般的Flask-WTF documentation 了解基本使用说明会很有帮助。

    【讨论】:

    • 我正在使用 form.hidden_​​tag() 它也呈现 csrf 令牌:flask-wtf.readthedocs.io/en/stable/…
    • @Lazypaddy 我没有在你发给我的文档中看到这一点,我自己也没有尝试过。
    • 我不知道如何在这里提供帮助。它只是工作...如果您在表单中使用 form.hidden_​​tag() 而不是 form.csrf_token 您将看到它插入了 csrf 令牌以及任何其他隐藏标签。 CSRF 令牌是一个隐藏标签。
    • 来自 Miguel Grinberg:form.hidden_​​tag() 模板参数生成一个隐藏字段,其中包含一个用于保护表单免受 CSRF 攻击的令牌。要保护表单,您需要做的就是包含此隐藏字段并在 Flask 配置中定义 SECRET_KEY 变量。如果您处理好这两件事,Flask-WTF 会为您完成其余的工作。 https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iii-web-forms
    【解决方案2】:

    所以在大量搜索和观看视频之后,我注意到在做 FormFields 时,所有内容都指的是 Form 而不是 FlaskForm。似乎您只能在页面上拥有一个 FlaskForm ......子表单必须是 Form 类。我将子表单更改为从 Form 而不是 FlaskForm 继承,并且它起作用了。 FlaskForm 继承自 Form 并且默认启用和配置了 csrf。

    class AddressForm(Form):
    
        address = StringField(label='Address', validators=[DataRequired()])
        address2 = StringField(label='Address 2', validators=[Optional()])
        city = StringField(label='City', validators=[DataRequired()])
        county = SelectField(label='County', validators=[DataRequired()], choices=[], coerce=int)
    
    
    class NameForm(Form):
        first_name = StringField(label='First Name', validators=[DataRequired(), Length(min=2)] )
        last_name = StringField(label='Last Name', validators=[DataRequired(), Length(min=2)] )
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-12
      • 2022-01-02
      • 2016-04-12
      • 2018-05-24
      相关资源
      最近更新 更多