我有一个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。
你包括 {{ 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文档 的基本使用说明上。
所以经过大量的搜索和看视频,我发现在做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)] )