WTForms FormField导致csrf_token错误。

问题描述 投票:0回答:2

我有一个flask项目,基本上有2个Form Classes,作为第三个Form Class中的子表单。我使用这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
2个回答
0
投票

你包括 {{ form.csrf_token }} 内的表单标签来使用CSRF保护。根据文档。

当使用FlaskForm时,像正常情况一样渲染表单的CSRF字段。

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

如果模板不使用FlaskForm,则在表单中渲染一个带有标记的隐藏输入。

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

您可能会发现,参考一般的 Flask-TF文档 的基本使用说明上。


-1
投票

所以经过大量的搜索和看视频,我发现在做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)] )

© www.soinside.com 2019 - 2024. All rights reserved.