Flask框架——Flask-WTF表单:数据验证、CSRF保护

上篇文章中,我们学习了Flask框架——消息闪现,这篇文章我们学习Flask框架——Flask-WTF表单:数据验证、CSRF保护。

Flask-WTF

表单负责收集网页中的数据,是Web应用程序的基本功能。

Flask-WTF是Flask框架的一个扩展,用来处理表单,它封装了WTForms,其特点有:

  • 能快速定义表单模板;
  • 验证表单数据;
  • 全局的csrf保护,能够保护所有表单免受跨站请求伪造(CSRF)的攻击;
  • 与 Flask-Uploads 一起支持文件上传
  • 国际化集成。

在WTForm表单中,主要的功能有验证用户提交的数据合法性、快速渲染模板、CSRF保护、文件上传和验证码等。

其安装方式很简单,执行如下代码即可:

pip install flask-wtf

在安装flask-wtf的过程中,系统会自动安装wtform。

WTForms

表单字段

WTforms包中包含各种表单字段的定义,WTForms支持HTML的字段有:

字段 说明
BooleanField 复选框,值为True或False,相当于HTML的
DateField 文本字段, 值为datetime.date格式
DateTimeField 文本字段, 值为datetime.datetime格式
IntegerField 文本字段, 值为整数
DecimalField 用于显示带小数的数字的文本字段,值为decimal.Decimal
FloatField 文本字段, 值为浮点数
RadioField 一组单选框
FileField 文件上传字段
SelectField 下拉列表
SelectMultipleField 下拉列表, 可选择多个值
SubmitField 表单提交按钮,相当于HTML的
StringField 文本字段,相当于HTML的
TextAreaField 多行文本字段,相当于HTML的
HiddenField 隐藏文本字段,相当HTML的
FormFiled 把表单作为字段嵌入另一个表单
FieldList 子组指定类型的字段
PasswordField 密码文本字段,相当于HTML的

validators验证器

WTForms支持的validators验证器有:

验证函数 说明
Email 验证是电子邮件地址
EqualTo 比较两个字段的值;常用于要求输入两次信息进行确认的情况
IPAddress 验证IPv4网络地址
Length 验证输入字符串的长度
NumberRange 验证输入的值在数字范围内
Optional 无输入值时跳过其它验证函数
DataRequired 确保字段中有数据
Regexp 使用正则表达式验证输入值
URL 验证url
AnyOf 确保输入值在可选值列表中
NoneOf 确保输入值不在可选列表中

注意:在使用上面的WTForms表单支持的HTML字段与验证函数之前,需要导入这些HTML字段与验证函数

好了,了解了WTForms表单支持的HTML字段与验证函数后,接下来我们通过示例代码来演示表单数据验证。

数据验证

创建一个Flask项目并在项目中创建一个名为form.py的表单类文件,当然文件名可以是任意的,在form.py文件中写入以下代码:

from flask_wtf import FlaskForm      #导入FlaskForm
from wtforms import StringField, PasswordField  #导入需要的字段
from wtforms.validators import DataRequired, length  #导入需要的验证函数

class MyForm(FlaskForm):
    name = StringField('name', validators=[DataRequired()]) #使用文本字段,数据不能为空验证
    password=PasswordField('password',validators=[DataRequired(),length(min=6,max=12)]) #使用密码文本字段,length长度验证

导入我们需要的FlaskForm、字段与验证函数,这里我们使用了StringField、PasswordField字段和DataRequired数据不能为空验证函数、length长度验证函数。

当然我们可以在字段中添加多个验证函数,只需要在validators验证器中添加验证函数即可,例如:将name = StringField(‘name’, validators=[DataRequired()])代码改为:

    name = StringField('name', validators=[DataRequired(),length(min=2,max=6)])

表单类文件已经写好了,接着在templates目录下创建一个名为form的html文件,然后在Flask项目的app.py文件中编写视图函数,代码如下所示:

from flask import Flask, render_template
from form import MyForm

app = Flask(__name__)

@app.route('/')
def user_form():
    myform=MyForm()     #创建表单类对象
    if myform.validate_on_submit():    
        return '提交成功'
    return render_template('form.html',myform=myform) #渲染form.html,并将myform表单对象传到form.html中

if __name__ == '__main__':
    app.run()

导入必要的包与库,在视图函数中创建刚才编写的表单类对象myform,validate_on_submit()方法检查是否是一个POST请求并且请求是否有效,再通过render_template()方法渲染form.html文件,并将myform传入form.html中。

app.py文件中的视图函数已经写好了,接下来编写刚才创建的form.html文件,其文件代码如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {#创建表单#}
    <form action="" method="post">
        <p>{{ myform.name }}</p>
        <p>{{ myform.password }}</p>
        <p>{{ myform.submit }}</p>
    </form>
</body>
</html>

在form.html文件中,我们通过{{ 表单类对象.属性 }}的方式渲染表单字段,当我们表单类字段定义中传入label参数时,还可以在模板文件中通过{{ 表单类对象.属性.label }}渲染该字段的label文本。

是不是这样就可以了呢,我们运行Flask项目,浏览器访问http://127.0.0.1:5000/,发现报了如下错误:

RuntimeError: A secret key is required to use CSRF.  #运行时错误:使用CSRF需要密钥

这时我们只需要在配置中添加SECRET_KEY即可,代码如下所示:

app.config['SECRET_KEY']='hakhfaskh'  #SECRET_KEY值是任意的

重新启动Flask项目并浏览http://127.0.0.1:5000/就不会报错了,如下图所示:

Flask框架——Flask-WTF表单:数据验证、CSRF保护

当我们没输入信息并按提交时,系统会自动提示浏览器内置的错误提示。

观察其源码,可以发现可以发现WTForm表单字段的第一个参数为表单的id和name的值。

自定义验证

一般来说,如果对表单有额外需要的验证,一般自定义表单的额外的验证方法而不是重新自定义新的字段,我们可以通过form.py表单类中使用validate_自定义验证,示例代码如下所示:

def validate_name(self,data):  #为name添加自定义validata_%s,并传入输入值data
    if self.name.data[0].isdigit():  #使用isdigit检验是否为数字开头,使用data[0]获取数据的首位
        raise ValidationError('用户名不能以数字开头')  #若验证不通过则抛出异常

这里我们为form.py表单类中的name添加自定义验证,所以自定义函数名为validate_name,如果我们为表单类中的password添加自定义验证时,自定义函数名为validate_password,也就是说自定义验证函数名要和表单类中字段名要对应。

这里我们为用户名添加了首字母不能以数字开头的验证,启动flask项目,并访问http://127.0.0.1:5000/,如下图所示:

Flask框架——Flask-WTF表单:数据验证、CSRF保护

CSRF保护

在上面的操作中,还没使用CSRF保护,在使用CSRF保护前,我们先了解一下CSRF的一些知识。

CSRF:跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性。

简单来说就是黑客盗用了你的身份,以你的名义发送恶意请求,服务器不知道是黑客请求的,服务器认为是你本人发出的请求。

其攻击原理如下图所示:

Flask框架——Flask-WTF表单:数据验证、CSRF保护

用户小明通过输入用户名、密码登录某安全网站A,网站服务器通过验证信息返回cookie给用户的浏览器,在未退出网站A或删除cookie期间,小明浏览了某不良网站B,不良网站B攻击代码来获取你安全网站A的cookie值并访问网站A,由于黑客拥有小明网站A的cookie,就可以以小明的身份访问网站A,以小明的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等操作。

很多网络诈骗是CSRF攻击,所以大家不要随便点击不明来路的链接和不要浏览不良网站。

那么如何防御CSRF攻击呢?

在Flask项目中,使用CSRFProtect()方法启动全局启用CSRF保护,代码如下所示:

from flask import Flask, render_template
from flask_wtf import CSRFProtect
from form import MyForm

app = Flask(__name__)
app.config['SECRET_KEY']='hakhfaskh'
#启动CSRF保护
csrf = CSRFProtect(app)

@app.route('/',methods=['GET','POST'])
def hello_world():
    myform=MyForm()     #创建表单类对象
    return render_template('form.html',myform=myform)

if __name__ == '__main__':
    app.run()

CSRF保护需要一个密钥,CSRF默认是使用配置的SECRET_KEY值,当然我们还可以单独使用WTF_CSRF_SECRET_KEY来设置。

在HTML文件中,我们需要渲染csrf_token或使用<input type=”hidden”来隐藏csrf_token代码如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <form action="" method="post">
        {{ myform.csrf_token }}   {#渲染csrf_token#}
        {# 使用<input type="hidden"隐藏csrf_token#}
{#        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
#}
        <p>{{ myform.name }}</p>
        <p>{{ myform.password }}</p>
        <p>{{ myform.submit }}</p>
    </form>
</body>
</html>

这样就成功使用了CSRF保护,启动Flask项目并访问http://127.0.0.1:5000/,如下图所示

Flask框架——Flask-WTF表单:数据验证、CSRF保护

当我们在网站中表单中填写信息会携带隐藏值提交给服务器,服务器根据隐藏值和用户填写的信息返回cookie值给用户,而cookie值没有隐藏值的信息,即使黑客获取到我们的cookie值,但无法获取隐藏值,没有隐藏值就无法得到服务器的信息验证。从而实现了CSRF保护、数据安全。

好了,关于Flask框架——Flask-WTF表单:数据验证、CSRF保护就讲到这里了,感谢观看,下篇文章学习Flask框架——Flask-WTF表单:文件上传、验证码。

– END –


原文始发于微信公众号(白巧克力LIN):Flask框架——Flask-WTF表单:数据验证、CSRF保护

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/36197.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!