7.添加session
逻辑是这样的,如果用户登录,那么就记录到
session
中,后续所有的操作都需要检查session
数据.# config.py
import os
from datetime import timedelta
# 配置session加密
SECRET_KEY = os.urandom(24)
# 设置超时时间
PERMANENT_SESSION_LIFETIME=timedelta(days=10)# app.py
# 登录页
class LoginView(views.MethodView):
def get(self):
return render_template('login.html')
def post(self):
# 验证表单
form = LoginForm()
if form.validate_on_submit():
# 表单验证成功,就跳转到数据库验证
print('表单验证成功')
email = form.email.data
password = form.password.data
lifetime = form.lifetime.data
# 数据库判断
print(email, password, lifetime)
exist_user = db.session.query(BankUsers).filter(BankUsers.email==email).filter(BankUsers.password==password).first()
print(exist_user)
if exist_user != None:
if lifetime:
session.clear()
session['username'] = exist_user.username
session.permanent = True
return redirect(url_for('personal'))
else:
session.clear()
session['username'] = exist_user.username
return redirect(url_for('personal'))
else:
return render_template('login.html', info=form.errors)
else:
return render_template('login.html', info="用户名密码不正确,请注册")如果点选
checkbox
,就设置cookie
时长,否则关闭浏览器后cookie
失效
不点选 checkbox
点选 checkbox
8.优化personal
优化显示
personal
中的数据.注意:
personal.html
中应该有接收后端数据的代码# app.py
# 个人信息页面
@app.route('/personal/')
def personal():
if session.get('username', None):
username = session['username']
balance = db.session.query(BankUsers.balance).filter(BankUsers.username == username).first()
return render_template('personal.html', username=username, balance=balance)
else:
return redirect(url_for('LoginView'))使用
session
登录之后,即可查询账户剩余金额
9.将session
存储在Redis
中
修改
config.py
指定保存的类型# redisModel.py
from redis import StrictRedis
redis = StrictRedis(host='192.168.0.101', port=6379)# config.py
import os
from datetime import timedelta
from redisModel import redis
DEBUG = True
TEMPLATES_AUTO_RELOAD = True
# 数据库支持
msg = "MySQL+pymysql://root:2008.Cn123@192.168.0.101:3306/flask_csrf_demo"
SQLALCHEMY_DATABASE_URI = msg
SQLALCHEMY_TRACK_MODIFICATIONS = False # 关闭追踪
# 显式关闭CSRF
WTF_CSRF_ENABLED = False
# 配置session加密
SECRET_KEY = os.urandom(24)
# 设置超时时间
PERMANENT_SESSION_LIFETIME=timedelta(days=10)
# session 保存在 redis中
# 指定Session保存类型
SESSION_TYPE = 'redis'
SESSION_USE_SIGNER = True # 加密
SESSION_KEY_PREFIX= 'session'
SESSION_REDIS = redis# app.py
from flask_session import Session as Fsession
Fsession(app登录账户后,查看
redis
,有session
开头的数据,说明成功.
10.修改存钱和转账页面
# app.py
# 存钱页面
class SaveMoneyView(views.MethodView):
def get(self):
if session.get('username', None):
return render_template('savemoney.html', user=session['username'])
else:
return redirect(url_for('login'))
def post(self):
form = SaveMoneyForm()
if form.validate_on_submit():
# 如果表单验证成功,则去session中查看 username
if session.get('username', None):
add_money = form.add_money.data
true_user = db.session.query(BankUsers).filter(BankUsers.username == session['username']).first()
true_user.balance += add_money
db.session.commit()
return redirect(url_for('personal', info='转账成功'))
else:
return redirect(url_for('login'))
else:
return render_template('savemoney.html', info='请输入正确的金额')
# 转账页面
class TransferView(views.MethodView):
def get(self):
if session.get('username', None):
return render_template('transfer.html', name=session['username'])
else:
return redirect(url_for('login'))
def post(self):
form = TransferForm()
if form.validate_on_submit():
# 表单验证成功后,转入验证session
if session.get('username', None):
money = form.transfer.data
transfer_name = form.transfer_name.data
username = session['username']
true_user = db.session.query(BankUsers).filter(BankUsers.username == username).first()
# 判断金额是否符合逻辑
if true_user.balance >= money:
true_user.balance -= money
# 转账账户
transfer_user = db.session.query(BankUsers).filter(BankUsers.username == transfer_name).first()
transfer_user.balance += money
# 提交事务
db.session.commit()
return redirect(url_for('personal', info='转账成功'))
else:
return render_template('transfer.html', info='余额不足')
else:
return redirect(url_for('login'))
else:
return render_template('transfer.html', info=form.errors)
# 退出
@app.route('/logout/')
def logout():
"""删除session"""
session.clear()
return render_template('index.html')注意,以上建立在确实有
session
的情况下.验证:注册2个账户,并发起转账操作,查看数据库中数据是否发生变化.
mysql root@192.168.0.101:flask_csrf_demo> select * from bankusers;
+----+----------------------+------------+------------+-------------+---------+
| id | email | username | password | phone | balance |
+----+----------------------+------------+------------+-------------+---------+
| 3 | ningwenyan@qq.com | ningwenyan | 123456789 | 18518506688 | 9000.0 |
| 4 | mytestuser@qq.com | mytestuser | 123456789 | 18518506688 | 1000.0 |
+----+----------------------+------------+------------+-------------+---------+
11.限制未登录用户
现在已经实现了登录的账户访问的页面的基本情况,但是还有一种情况,那就是没有注册过的 账户, 如果知道
URL
,也会访问到savemoney.htmltransfer.html
页面,为了避免这种情况,我们需要做出限制,让没有登录的账户不能访问我们的相关页面.在
views.MethodView
中有一个decorators
的功能,可以起到装饰器的作用,可以把验证的函数放在这个里面>>> from flask import views
>>> help(views.MethodView.decorator# limit.py
from functools import wraps
from flask import redirect,url_for,session
def limit_session(func):
@wraps(func)
def wrapper(*args,**kwargs):
username = session.get('username',None)
if username:
return func(*args,**kwargs)
else:
session.clear()
return redirect(url_for('login'))
return wrapper# app.py
# 存钱页面
class SaveMoneyView(views.MethodView):
decorators = [limit_session]
def get(self):
if session.get('username', None):
return render_template('savemoney.html', user=session['username'])
else:
return redirect(url_for('login'))
def post(self):
form = SaveMoneyForm()
if form.validate_on_submit():
# 如果表单验证成功,则去session中查看 username
if session.get('username', None):
add_money = form.add_money.data
true_user = db.session.query(BankUsers).filter(BankUsers.username == session['username']).first()
true_user.balance += add_money
db.session.commit()
return redirect(url_for('personal', info='转账成功'))
else:
return redirect(url_for('login'))
else:
return render_template('savemoney.html', info='请输入正确的金额')
# 转账页面
class TransferView(views.MethodView):
decorators = [limit_session]
def get(self):
if session.get('username', None):
return render_template('transfer.html', name=session['username'])
else:
return redirect(url_for('login'))
def post(self):
form = TransferForm()
if form.validate_on_submit():
# 表单验证成功后,转入验证session
if session.get('username', None):
money = form.transfer.data
transfer_name = form.transfer_name.data
username = session['username']
true_user = db.session.query(BankUsers).filter(BankUsers.username == username).first()
# 判断金额是否符合逻辑
if true_user.balance >= money:
true_user.balance -= money
# 转账账户
transfer_user = db.session.query(BankUsers).filter(BankUsers.username == transfer_name).first()
transfer_user.balance += money
# 提交事务
db.session.commit()
return redirect(url_for('personal', info='转账成功'))
else:
return render_template('transfer.html', info='余额不足')
else:
return redirect(url_for('login'))
else:
return render_template('transfer.html', info=form.errors)当我们删除
cookie
后,再次访问savemoney.htmltransfer.html
页面, 会自动跳转到登录页面.这样保障了数据的安全.
– END –
原文始发于微信公众号(Flask学习笔记):CSRF攻击和防护(3)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/36484.html