Flask-WTF
4.1跨站请求伪造保护
默认情况下,Flask-WTF能保护所有表单免受跨站请求伪造的攻击。恶意网站把请求发送到被攻击者已登陆的其他网站时就会引发CSRF攻击。
详细的CSRF攻击原理见:https://www.cnblogs.com/wangyuyu/p/3388169.html
为了实现CSRF保护,Flask-WTF需要程序设置一个秘钥,然后根据这个秘钥生成加密令牌,再用令牌验证请求中表单数据的真伪。设置秘钥的方法为:
#hello.py:设置Flask-WTF
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
app.config字典用来存储框架、扩展和程序本身的配置变量。
SECRET_KEY配置变量是通用秘钥,加密的程度取决于变量值得机密程度。不同的程序要使用不同的秘钥,而且要保证其他人不知道你所用的字符串。
4.2 表单类
使用Flask-WTF时,每个web表单都由一个继承自Form的类表示。这个类定义表单中的一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数。验证函数用来验证用户提交的输入值是否符合要求。
#hello.py:定义表单类,包含一个文本字段和一个提交按钮。
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required
class NameForm(Form):
name = StringField('What is your name?', validators=[Required()])
submit = SubmitField('Submit')
StringField类表示属性为 type="text" 的 <input> 元素。 SubmitField 类表示属性为 type="submit" 的<input> 元素。字段构造函数的第一个参数是把表单渲染成 HTML 时使用的标号。
StringField 构造函数中的可选参数 validators 指定一个由验证函数组成的列表,在接受用户提交的数据之前验证数据。验证函数 Required() 确保提交的字段不为空。
4.3 把表单渲染成HTML
表单字段时可调用的,在模板中调用后会渲染成HTML。
4.4 在视图函数中处理表单
4.5 重定向和用户会话
程序可以把数据存储在用户会话中,在请求之间“记住”数据。用户会话是一种私有存储,存在于每个连接到服务器的客户端中。
4.6 Flash消息
请求完成后,有时需要让用户知道状态发生了变化。这里可以使用确认消息、警告或者错误提醒。一个典型例子是,用户提交已一项错误的登录表单后,服务器发回的响应重新渲染了登录表单,并在表单上面显示一个消息,提示用户用户名或密码错误。
这种功能是 Flask 的核心特性。flash() 函数可实现这种效果。
#hello.py:Flash消息
from flask import Flask, render_template, session, redirect, url_for, flash
@app.route('/', methods=['GET', 'POST'])
def index():
form = NameForm()
if form.validate_on_submit():
old_name = session.get('name')
if old_name is not None and old_name != form.name.data:
flash('Looks like you have changed your name!')
session['name'] = form.name.data
return redirect(url_for('index'))
return render_template('index.html',
form = form, name = session.get('name'))
Flask把get_flashed_messages函数开放给模板,用来获取并渲染消息。
# templates/base.html:渲染Flash信息
{% block content %}
<div class="container">
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ message }}
</div>
{% endfor %}
{% block page_content %}{% endblock %}
</div>
{% endblock %}