Falsk框架 Session 与 Flask-Session
Cookie 与 Session 简单了解
Cookie: #存储大小受限,储存在客户端,有安全隐患
Cookie意为“甜饼”,是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、
Netscape、Firefox、Opera等都支持Cookie。由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?
就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
Session: #来完善Cookie
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,
服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了,
实质上session就是保存在服务器端的键值对。
Falsk 中 Session 的保管机制
交由客户端保管机制 实现过程
1.开启并设置 Session - session["user"] = 123
2.session 序列化字符串
3.通过 secret_key密钥 进行加密
4.通过 Cookie 返回客户端
接收Session
1.通过客户端 Cookie 获取 session
2.通过 secret_key密钥 进行解密
3.反序列化 字典
4.得到 session
优点:不占用服务器资源
缺点:保存在客户端,安全性相对较差
#一般我们都会使用三方组件提供的session模块,来解决flask session的安全问题,如 Flask-Session这个组件就可以帮我们解决问题.
相关的配置
Flask 中的 Session
- from flask import session
- 使用session的前提是在 application 中加入 secret_key 如:app.secret_key = "!@#$%^&*()"
#Session 相关配置 想要配置生效必须在代码中重新配置 重启后生效
"SECRET_KEY": None, # 通用密钥
# 设置方法 app.secret_key = "!@#$%^&*()"(编码方便) 或 app.config['SECRET_KEY'] = "!@#$%^&*()"(效率高)
session.pop('username') #删除session中的username对应的键和值
session.clear() #删除所有session
"SESSION_COOKIE_NAME": "session",
# 设置session 在Cookie Session名称 app.session_cookie_name = 'session'
"SESSION_COOKIE_HTTPONLY": True,
# 是否只在HTTP请求下开启 session
############################### 其他配置 ###############################
{
'DEBUG': False,
# 是否开启Debug模式 开发环境 log级别低 重启代码错误透传
'TESTING': False,
# 是否开启测试模式 测试环境 log级别较高
'PROPAGATE_EXCEPTIONS': None,
# 异常传播(是否在控制台打印LOG) 当Debug或者testing开启后,自动为True
'PRESERVE_CONTEXT_ON_EXCEPTION': None,
# 一两句话说不清楚,一般不用它
'SECRET_KEY': None,
# 开启Session序列化,在启用Session的时候,一定要有它
'PERMANENT_SESSION_LIFETIME': 31,
# Session的生命周期(秒)默认31秒
'USE_X_SENDFILE': False,
# 是否弃用 x_sendfile
'LOGGER_NAME': None,
# 日志记录器的名称
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None, # 服务访问域名
'APPLICATION_ROOT': None, # 项目的完整路径
'SESSION_COOKIE_NAME': 'session', # 在cookies中存放session加密字符串的名字
'SESSION_COOKIE_DOMAIN': None, # 在哪个域名下会产生session记录在cookies中
'SESSION_COOKIE_PATH': None, # cookies的路径
'SESSION_COOKIE_HTTPONLY': True, # 控制 cookie 是否应被设置 httponly 的标志,
'SESSION_COOKIE_SECURE': False, # 控制 cookie 是否应被设置安全标志
'SESSION_REFRESH_EACH_REQUEST': True, # 这个标志控制永久会话如何刷新
'MAX_CONTENT_LENGTH': None,
# 如果设置为字节数, Flask 会拒绝内容长度大于此值的请求进入,并返回一个 413 状态码
'SEND_FILE_MAX_AGE_DEFAULT': 12, # hours 默认缓存控制的最大期限
'TRAP_BAD_REQUEST_ERRORS': False,
# 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样,
# 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。
'TRAP_HTTP_EXCEPTIONS': False,
# Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。
# 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。
# 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。
# 如果这个值被设置为 True ,你只会得到常规的回溯。
'EXPLAIN_TEMPLATE_LOADING': False,
'PREFERRED_URL_SCHEME': 'http', # 生成URL的时候如果没有可用的 URL 模式话将使用这个值
'JSON_AS_ASCII': True,
# 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False ,
# Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。
# 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。
'JSON_SORT_KEYS': True,
#默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。
# 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。
# 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。
'JSONIFY_PRETTYPRINT_REGULAR': True,
'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None,
}
使用 Flask-Session 三方组件
安装
#flask_session是flask框架实现session功能的一个插件,用来替代flask自带的session实现机制。
#安装
pip3 install flask-session
#Flask-Session 支持 session保存到多个地方如:
- redis #存放在内网使用,不要存放在公网
- memcached
- filesystem
- mongodb
- sqlalchmey
#存放在redis实例
import redis
from flask import Flask, session
from flask_session import Session
app = Flask(__name__)
app.debug = True
app.secret_key = 'xxxx'
app.config['SESSION_TYPE'] = 'redis' # session类型为redis
app.config['SESSION_PERMANENT'] = False # 如果设置为True,则关闭浏览器session就失效。
app.config['SESSION_USE_SIGNER'] = False # 是否对发送到浏览器上session的cookie值进行加密
app.config['SESSION_KEY_PREFIX'] = 'session:' # 保存到session中的值的前缀
app.config['SESSION_REDIS'] = redis.Redis(host='127.0.0.1', port='6379', password='123123') # 用于连接redis的配置
Session(app)
@app.route('/index')
def index():
session['k1'] = 'v1'
return 'xx'
if __name__ == '__main__':
app.run()
Flask-Session文件目录
################################ 代码 ################################
# __init__.py Session配置代码
from flask import Flask,request,session
from flask_session import Session
from redis import Redis
from app01.views.user import user_bp
def create_app():
app = Flask(__name__)
app.config["DEBUG"] = True
app.config["SESSION_TYPE"] = "redis"
app.config["SESSION_REDIS"] = Redis(host="127.0.0.1",port=6379,db=15)
# app.session_interface = SecureCookieSessionInterface() # 原生 Session
# 在Config之后
# 三方组件存活的空间
Session(app) #完成flask_session 对原生 Session的替换
# 在蓝图导入之前
app.register_blueprint(user_bp)
return app
# app01.py 蓝图代码
from flask import Blueprint
# 蓝图是Flask实例,不可被run
user = Blueprint("user",__name__,url_prefix="/user") # Blueprint name 不能再同一个Flask实例中重复
@user.route("/reg")
def reg():
return "user注册成功"
@user.route("/login")
def login():
return "user登录成功"
基础练习题
需求
使用以下数据制作学生详情页面
STUDENT_DICT = {
1: {'name': '钢蛋', 'age': 17, 'gender': '不详'},
2: {'name': '铁蛋', 'age': 19, 'gender': '男'},
3: {'name': '丫蛋', 'age': 18, 'gender': '女'},
}
要求:
1.编写登录页面 登录成功跳转到 学生概况页面
2.学生概况页面 只显示学生的 ID name 详细信息需点击后访问 学生详情页面页面查看
3.学生详情页面 显示这个学生的所有信息ID name age gender
4.基于Session编写登录验证装饰器 未登录状态只能访问 登录页面 登录成功后才可以访问 学生概况页面 与 学生详情页面
参考答案 (python代码)
from flask import Flask, request, render_template, redirect, session
STUDENT_DICT = {
1: {'name': '钢蛋', 'age': 17, 'gender': '不详'},
2: {'name': '铁蛋', 'age': 19, 'gender': '男'},
3: {'name': '丫蛋', 'age': 18, 'gender': '女'},
}
app = Flask(__name__, template_folder='templates')#实例化一个Flask类,指定模板存放位置
app.secret_key = "!@#$%^&*()" # 密钥(对session进行加密)
app.debug = True # 开启Debug模式 修改代码自动重启项目
def check(func): # 装饰器 检测用户是否登录 利用session中的user的值做判断
def inner(*args, **kwargs):
if session.get('user') == 'gkf':
ret = func(*args, **kwargs)
return ret
else:
return redirect('/login')
return inner
@app.route('/login', methods=['POST', 'GET'], endpoint='login')#指定路由与接受请求方式,设置endpoint
def login():
if request.method == 'GET':
return render_template('login.html') #如果是get请求返回一个login.html
if request.method == 'POST': #如果是post请求,把request.form中页面输入的值取出
username = request.form.get('username').lower()
password = request.form.get('password')
if username == 'gkf' and password == '123':#如果账户密码正确,设置 session["user"] = username
session["user"] = username
return redirect('/brief_introduction') #重定向到brief_introduction
else:
return '账号或密码错误' #如果账户密码不对,抛出错误提示
#设置endpoint='brief_introduction'让其与其他的视图函数不冲突,才能正常使用装饰器
@app.route('/brief_introduction', methods=('GET',), endpoint='brief_introduction')
@check #装饰器 必需添加在@app.route()下,不然会导致,使用装饰器导致@app.route()不被识别,报错
def brief_introduction():
return render_template('brief_introduction.html', st_obj=STUDENT_DICT)#返回brief_introduction.html 并传入STUDENT_DICT字典 调用名字为st_obj
@app.route('/detailed', methods=('GET',), endpoint='detailed')
@check
def detailed(): #取出前端页面返回的url携带的学生编号, 并把它传给模板detailed.html 进行渲染
s_id = request.args.get('id') #对url携带参数做效验,确保返回的学生编号正确
if not s_id:
return "查询错误请重试"
if not s_id.isdecimal():
return "查询错误请重试"
s_id = int(s_id)
num = STUDENT_DICT.get(s_id,'')
if not num:
return "查询错误请重试"
else:
return render_template('detailed.html', id=s_id, st_obj=STUDENT_DICT)
if __name__ == '__main__':
app.run()
参考答案 (html代码)
<!--templates 下 login.html 代码-->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>登录</title>
</head>
<body>
<h1>用户登录</h1>
<form action="" method="post" enctype="multipart/form-data">
<p>用户名: <input type="text" name="username"></p>
<p>密码: <input type="password" name="password"></p>
<input type="submit" value="登录">
</form>
</body>
</html>
<!--templates 下 brief_introduction.html 代码-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生信息简介</title>
</head>
<body>
<h1>学生信息简介</h1>
<table border="1px">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for foo in st_obj %}
<tr>
<td>{{ foo }}</td>
<td>{{ st_obj[foo].name }}</td>
<!--把学生对应的编号添加到detailed的url上-->
<td><a href="http://127.0.0.1:5000/detailed?id={{ foo }}">点击查看详情<a></td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
<!--templates 下 detailed.html 代码-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生详细信息</title>
</head>
<body>
<h1>学生详细信息</h1>
<table border="1px">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ id }}</td>
<td>{{ st_obj[id].name }}</td>
<td>{{ st_obj[id].age }}</td>
{% if st_obj[id].gender=='不详' %}<!--判断对不正常的性别,修改显示结果-->
<td>男</td>
{% else %}
<td>{{ st_obj[id].gender }}</td>
{% endif %}
</tr>
</tbody>
</table>
</body>
</html>
Falsk框架 Session 与 Flask-Session的更多相关文章
- 初识Flask框架,以及Flask中的模板语言jinjia2和Flask内置的Session
一.web框架的对比 首先我们先来看下比较火的web框架 1.Django: 优点:大而全,所有组件都是组织内部开发高度定制化,教科书级别的框架 缺点:大到浪费资源,请求的时候需要的资源较高 2.Fl ...
- flask框架基本使用(3)(session与cookies)
#转载请留言联系 flask 框架基本使用(1):https://www.cnblogs.com/chichung/p/9756935.html flask 框架基本使用(2):https://www ...
- Flask框架(五) —— session源码分析
Flask框架(五) —— session源码分析 目录 session源码分析 1.请求来了,执行__call__方法 2.__call__方法 3.调用__call__方法 3.1.ctx = s ...
- Flask框架【七】—session组件详解
一.flask session简介 flask中session组件可分为内置的session组件还有第三方flask-session组件,内置的session组件缺点: 功能单一 session是保存 ...
- flask 状态保持session和上下文session的区别
问题场景: 在falsk项目中导入了两个session: 首先,配置文件config.py文件中 有个 flask_session扩展导入了Session ( from flask_sessi ...
- flask-admin章节四:flask session的使用
1. 关于session flask session可能很多人根本都没有使用过,倒是cookie大家可能使用得比较多.flask cookie使用起来比较简单,就两个函数,读取和设置. 具体使用方式如 ...
- falsk 与 django cookie和session存、取、删的区别
falsk cookie的存取删需导入from flask import Flask,make_response,request# 存COOKIE的方法@app.route('/setcookie') ...
- flask session,蓝图,装饰器,路由和对象配置
1.Flask 中的路由 *endpoint - url_for 反向地址 *endpoint 默认是视图函数名 *methods 指定视图函数的请求方式,默认GET defaults={& ...
- 【Flask】Flask Session操作
### session:1. session的基本概念:session和cookie的作用有点类似,都是为了存储用户相关的信息.不同的是,cookie是存储在本地浏览器,session是一个思路.一个 ...
随机推荐
- Sonar错误 Invoke method(s) only conditionally
sonarLint总是报错: Invoke method(s) only conditionally 代码如下: if(us != null){ logger.info("Log this: ...
- Spring生态研习【五】:Springboot中bean的条件注入
在springboot中,开发的确变的简单了很多,但是,开发者现在希望开发傻瓜式的方便搞定项目中的各种奇怪的需求最好了,不用烧脑,本来程序猿的生活就是枯燥的,不要再给自己添加更多的烦恼. 今天,就为了 ...
- redis支持远程接入的安全防护问题
如果我们没有启用保护模式,支持远程接入,启用默认端口6379,而且是用root用户启动的,那么基本上redis就是在裸奔了,人家分分钟搞你没商量. 我们模拟一下,现在机器A(ip假设为10.100.1 ...
- but only one is allowed(重复处理跨域请求)
情景:vue的项目中在本地调试项目,在前端的跨域配置没有问题的情况下,出现这样的报错. 解决方案,参考: https://www.cnblogs.com/zsg88/articles/11576324 ...
- OpenShift 4.2环境离线部署Operatorhub
缺省离线环境安装的ocp4的Operatorhub是没有内容的.详细离线文档参考官网文档 https://docs.openshift.com/container-platform/4.2/opera ...
- ETF参数:现金替代标志
表示该股票是否允许用现金进行替代. 0表示沪市股票禁止现金替代(必须有股票) 1表示沪市股票可以进行现金替代(先用股票,股票不足的话用现金替代) 2表示沪市股票必须用现金替代. 对于跨市场ETF,3表 ...
- Kubernetes之在k8s中部署Java应用
部署好了k8s以后 部署参考https://www.cnblogs.com/minseo/p/12055731.html 怎么在k8s部署应用 项目迁移到k8s平台是怎样的流程 1,制作镜像 2,控制 ...
- Putty——支持Telnet,ssh连接的连接软件
简介 PuTTY 的官方网站:http://www.chiark.greenend.org.uk/~sgtatham/putty/,截止到 2007年6月,发布的最高稳定版本是 0.6.PuTTY 是 ...
- django:将query-set类型转为json类型
import json data = json.dumps(list(my_table.objects.all().values())) return HttpResponse(data)
- Vue父子组件相互传值及调用方法的方案
Vue父子组件相互传值及调用方法的方案 一.调用方法: 1.父组件调用子组件方法: 2.子组件调用父组件方法: 参考:https://www.cnblogs.com/jin-zhe/p/9523782 ...