一、过滤器
1.字符串操作
- 格式
{{variable | filter name[(*args)] | filter name2
- safe 禁用转义
{{ 'hello'|safe }}
- capitalize变量首字母大写
{{ 'hello'|capitalize }}
- upper 转化成大写
{{ 'hello'|upper }}
- lower 转化成小写
{{ 'HELLO'|lower }}
- title 单词首字母大写
{{ 'hello lx'|title }}
- '%s is %d'|format('李现',28) 格式化输出
{{ '%s is %d'|format('李现',28) }}
- reverse 字符串反转
{{ 'hello'|reverse }}
- striptags 渲染之前把所有的html标签都去掉
{{ 'hello'|striptags }}
示例:
- 新建一个demo_for_filter.py文件
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
#render_template进行模板渲染
return render_template('demo-filter.html')
if __name__ == '__main__':
app.run(debug=True)
- 在templates文件夹下新建一个demo-filter.html文件
Title
常见内建过滤器
{{ 'hello'|safe }}
hello
{{ 'hello'|capitalize }}
{{ 'hello'|upper }}
{{ 'HELLO'|lower }}
{{ 'hello lx'|title }}
{{ '%s is %d'|format('李现',28) }}
{{ 'hello'|reverse }}
{{ 'hello'|striptags }}
-
运行程序
2.列表操作
- first 显示列表第一个元素
{{ [1,2,3] |first }}
- last 显示列表最后一个元素
{{ [2,3,4] |last }}
- length 显示列表长度
{{ [2,3,4] |length }}
- sum 列表数列求和
{{ [2,3,4] |sum }}
- sort 列表排序
{{ [2,4,3] |sort }}
示例:
列表操作
{{ [1,2,3] |first }}
{{ [2,3,4] |last }}
{{ [2,3,4] |length }}
{{ [2,3,4] |sum }}
{{ [2,4,3] |sort }}
二、验证表单数据(WTF)
1.表单验证
- 新建一个demo_wrf1.py文件
from flask import Flask, render_template, request, redirect, url_for, flash
app = Flask(__name__)
app.secret_key = 'soda'
@app.route('/')
def index():
return "soda"
@app.route('/demo1',methods=["get","post"])
def demo1():
if request.method == 'POST':
#获取表单的三个参数
username = request.form.get("username","")
password = request.form.get("password","")
password2 = request.form.get("password2","")
print(username,password,password2)
return 'success'
return render_template("login.html")
if __name__ == '__main__':
app.run(debug=True)
- 在templates文件夹内建一个login.html文件
Title
用户登录页面
-
运行
2.flash闪现
- 修改demo_wrf1.py文件
from flask import Flask, render_template, request, redirect, url_for, flash
app = Flask(__name__)
app.secret_key = 'soda'
@app.route('/')
def index():
return "soda"
@app.route('/demo1',methods=["get","post"])
def demo1():
if request.method == 'POST':
#获取表单的三个参数
username = request.form.get("username","")
password = request.form.get("password","")
password2 = request.form.get("password2","")
if not all([username,password,password2]):
#向前端闪现一个参数不足的消息
flash("参数不足")
elif password != password2:
flash("两次密码不一致")
else:
print(username,password,password2)
return 'success'
return render_template("login.html")
if __name__ == '__main__':
app.run(debug=True)
- 修改login.html文件
Title
用户登录页面
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
-
运行
3.WTF表单验证
- 安装flask_wtf
pip install flask_wtf
- 新建一个demo_wtf2.py文件
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, EqualTo
app = Flask(__name__)
class RegisterForm(FlaskForm):
username = StringField("用户名:",validators=[DataRequired("请输入用户名")],render_kw={"placeholder":"请输入用户名"})
password = PasswordField("密码:",validators=[DataRequired("请输入密码")],render_kw={"placeholder":"请输入密码"})
password2 = PasswordField("确认密码:",validators=[DataRequired("请输入确认密码"),EqualTo("password","两次密码不一致")],render_kw={"placeholder":"请输入确认密码"})
submit = SubmitField("注册")
app.secret_key = 'soda'
app.config['WTF_CSRF_ENABLED'] = False
@app.route('/')
def index():
return "soda"
@app.route('/demo1', methods=["get","post"])
def demo1():
register_form = RegisterForm()
if register_form.validate_on_submit():
#如果代码走到if里面证明表单验证有效
username = request.form.get("username")
password = request.form.get("password","")
password2 = request.form.get("password2","")
print(username,password,password2)
return "success"
else:
if request.method =='POST':
flash("表单参数有误或者不完整")
return render_template("login2.html",form = register_form)
if __name__ == '__main__':
app.run(debug=True)
- 在templates文件夹下创建一个login2.html文件
Title
WTF用户登录页面
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
-
输入正确的密码时:
-
输入不正确的密码时:
三、转账例子
- 新创建一个webA.py文件
from flask import Flask, request, render_template, redirect, url_for, flash, make_response
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField,SubmitField
from wtforms.validators import DataRequired,EqualTo
app = Flask(__name__)
app.config['WTF_CSRF_ENABLED'] = False
app.secret_key = 'dasdasdsadas'
@app.route('/', methods=["get", "post"])
def index():
if request.method =='POST':
# 取出表单数据
username = request.form.get("username")
password = request.form.get("password", "")
if not all([username, password]):
print('参数错误')
else:
print(username, password)
if username == 'admin' and password == '1234':
# 登录成功跳转到转账页面
response = redirect(url_for('transfer'))
# 因为转账要求用户登录,所以我们进行状态保持,设置用户名到cookie中
response.set_cookie('username',username)
return response
else:
print('密码错误')
return render_template("login3.html")
@app.route('/transfer', methods=["get", "post"])
def transfer():
# 取出cookie,确保是登录的
username = request.cookies.get('username',None)
if not username:
# 没有代表没登录,跳转到登录页面
return redirect(url_for('index'))
if request.method == 'POST':
to_account = request.form.get("to_account")
money = request.form.get("money")
print('假装执行转账')
return '转账{}元到{}账户成功!'.format(to_account, money)
response = make_response(render_template('transfer.html'))
return response
if __name__ == '__main__':
app.run(debug=True)
- 在templates文件夹下创建一个login3.html文件
Title
用户登录页面
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
- 在templates文件夹下创建transfer.html文件
Title
我是网站A,转账页面
-
运行程序
四、CSRF攻击
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本XSS相比,XSS利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。(百度百科)
- 新建一个webB.html文件
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('tempb-index.html')
if __name__ == '__main__':
app.run(debug=True, port=8000)
- 在templates文件夹下创建tempb-index.html文件
Title
我是网站B
-
将webA.py文件和webB.py文件同时运行
点击网站B的时候它能够获取网站A的信息,这样的情况在转账的时候是十分不安全的,所以我们将避免这种情况:
- 打开webA.py文件
import base64
from flask import Flask, request, render_template, redirect, url_for, flash, make_response
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField,SubmitField
from wtforms.validators import DataRequired,EqualTo
import os
app = Flask(__name__)
app.config['WTF_CSRF_ENABLED'] = False
app.secret_key = 'dasdasdsadas'
@app.route('/', methods=["get", "post"])
def index():
if request.method =='POST':
# 取出表单数据
username = request.form.get("username")
password = request.form.get("password", "")
if not all([username, password]):
print('参数错误')
else:
print(username, password)
if username == 'admin' and password == '1234':
# 登录成功跳转到转账页面
response = redirect(url_for('transfer'))
# 因为转账要求用户登录,所以我们进行状态保持,设置用户名到cookie中
response.set_cookie('username',username)
return response
else:
print('密码错误')
return render_template("login3.html")
@app.route('/transfer', methods=["get", "post"])
def transfer():
# 取出cookie,确保是登录的
username = request.cookies.get('username',None)
if not username:
# 没有代表没登录,跳转到登录页面
return redirect(url_for('index'))
if request.method == 'POST':
to_account = request.form.get("to_account")
money = request.form.get("money")
# 取出表单的 crsf_token
form_crsf_token = request.form.get("crsf_token")
# 取出 cookie的crsf_token
cookie_crsf_token = request.cookies.get('crsf_token')
if form_crsf_token != cookie_crsf_token:
return "token校验失败,可能是非法操作"
print('假装执行转账')
return '转账{}元到{}账户成功!'.format(to_account, money)
# 使用 make_response, 相当于 django的httpresponse
# 生成 crsf_token
crsf_token = generate_crsf()
response = make_response(render_template('transfer.html', crsf_token= crsf_token))
# 用于提交验证
response.set_cookie('crsf_token',crsf_token)
return response
def generate_crsf():
return bytes.decode(base64.b64encode(os.urandom(48)))
if __name__ == '__main__':
app.run(debug=True)
- 在templates/transfer.html文件中添加一行代码
-
运行webA.py和webB.py文件
在网站A页面进行登陆到转账页面:
再打开网站B进行攻击,会发现攻击不了:
- 代码解析:
def generate_crsf():
return bytes.decode(base64.b64encode(os.urandom(48)))
这个代码的作用,就是产生一串48位的字符:
- 如果要对表单设置防攻击的话直接写一行代码就可以:
{{ form.crsf_token }}
from flask_wtf import CSRFProtect
CSRFProtect(app)
这算是个简单的阻断srsf攻击的方法,以后会进行完善。
(此文章仅作为个人学习笔记使用,如有错误欢迎指正~)