4.1 Web 表单¶
4.1.1 跨站请求伪造保护¶
跨站请求伪造(CSRF):是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。
CSRF 攻击原理:
用户打开浏览器,访问受信任网站 A。登录成功后,网站 A 产生 Cookie 信息并返回给浏览器。
用户未退出网站 A 之前,在同一浏览器中,打开一个页面访问网站 B。
网站 B 接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A。
浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带 Cookie 信息,向网站A发出请求。网站 A 并不知道该请求其实是由 B 发起的,所以会根据用户的 Cookie 信息处理该请求,导致来自网站 B 的恶意代码被执行。
在 Flask 中, Flask-WTF 可以保护表单免受跨站请求伪造攻击。为了实现 CSRF 保护,Flask-WTF 需要应用程序配置一个加密密钥。Flask-WTF 使用这个加密密钥去生成安全令牌存储在用户会话中,用于验证请求表单数据的真实性。
示例:在 Flask 应用中配置密钥
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
app.config 字典可用来存储 Flask、扩展和程序自身的配置变量。
4.1.2 表单类¶
使用 Flask-WTF 时, 在服务器端,每个 Web 表单都是由一个继承 FlaskForm 的类表示。这个类定义表单中的一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数,用于验证用户提交的数据是否有效。
示例:定义一个简单的 Web 表单,包含一个文本字段和一个提交按钮。
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField
from wtforms.validators import DataRequired
class NameForm(FlaskForm):
name = StringField('What is your name?',validators=[DataRequired()])
submit = SubmitField('Submit')
WTForms支持的 HTML 标准字段(部分):
字段类型 |
说明 |
---|---|
BooleanField |
复选框,值为 True 和 False |
FileField |
文件上传字段 |
TextAreaField |
多行文本字段 |
StringField |
文本字段 |
SubmitField |
表单提交按钮 |
SelectField |
下拉列表 |
PsswordField |
密码文本字段 |
HiddenField |
隐藏的文本字段 |
WTForms 内建的验证函数(部分):
验证函数 |
说明 |
---|---|
DataRequired |
确保转换类型后的字段中有数据 |
验证电子邮件地址 |
|
EqualTo |
比较两个字段的值;常用于要求输入两次密码进行确认的情况 |
InputRequired |
确保转换类型前字段中有数据 |
IPAddress |
验证 IPV4 网络地址 |
Length |
验证输入字符串的长度 |
Regexp |
使用正则表达式验证输入值 |
4.1.3 把表单渲染成HTML¶
表单字段是可调用的,在模板中调用后会渲染成 HTML。假设视图函数通过 form 参数把一个 NameForm 实例传入模板,在模板中生成一个简单的HTML 表单:
<form method="POST">
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>
除了上面这种简单的方式,还可以使用 Flask-Bootstrap 渲染表单:
{% import "boostrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
4.1.4 在视图函数中处理表单¶
在视图函数中有两个任务:接收用户在表单中填写的数据、渲染表单。
示例:
@app.route('/',methods=['GET','POST'])
def index():
name = None
form = NameForm()
if form.validate_on_submit():
name = form.name.data
form.name.data = ''
return render_template('index.html', form=form, name=name)