Flask第三方组件之flask_session
flask默认提供了session, 但是存在以下问题:
① session数据存在客户端, 不安全
② 大小有限制
③ 增加了客户端的压力
所以才产生了很多第三方的session机制, 我使用的是flask_session, 也是官方认可的一个.
安装flask_session

如何使用flask_session
导入flask_session
from flask_session import Session
重新封装flask的session机制
实例化一个Session对象, 将flask实例传进去
app = Flask(__name__)
app.config["SESSION_TYPE"] = 'redis' # 如何存放session
app.config["SESSION_REDIS"] = redis.Redis(host="192.168.233.128", port=6379) # 连接redis的配置
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=1) #session的有效期
Session(app)
flask默认的session是存放在浏览器中的, 这个使用flask_session, 我准备将session存放在redis中, 所以需要做这些配置
下面看看Session实例化时都做了些什么
Session对app做了些什么?
class Session(object):
def __init__(self, app=None):
self.app = app
if app is not None:
self.init_app(app)
形参app就是传进来的app实例, 所有就会执行self.init_app(app), 看看有做了什么?
def init_app(self, app):
app.session_interface = self._get_interface(app)
这个函数很无聊, 就调用了一个self._get_interface(app), 其实session_interface就是flask所需要的一个操作session的接口, 在这里重新提供了一个接口, 当在进行session存取时候, 就会使用这个新的存取方式
def _get_interface(self, app):
config = app.config.copy() # 将flask实例的配置config拷贝了一份
# 设置这些值, 如果已经存在就不会再设置了
config.setdefault('SESSION_TYPE', 'null') # session存储的类型
config.setdefault('SESSION_PERMANENT', True)
config.setdefault('SESSION_USE_SIGNER', False)
config.setdefault('SESSION_KEY_PREFIX', 'session:') # 存在数据中的key中前缀, 最后就会看到, 类似于session: uuid4
config.setdefault('SESSION_REDIS', None) # redis连接
config.setdefault('SESSION_MEMCACHED', None)
config.setdefault('SESSION_FILE_DIR',
os.path.join(os.getcwd(), 'flask_session'))
config.setdefault('SESSION_FILE_THRESHOLD', 500)
config.setdefault('SESSION_FILE_MODE', 384)
config.setdefault('SESSION_MONGODB', None)
config.setdefault('SESSION_MONGODB_DB', 'flask_session')
config.setdefault('SESSION_MONGODB_COLLECT', 'sessions')
config.setdefault('SESSION_SQLALCHEMY', None)
config.setdefault('SESSION_SQLALCHEMY_TABLE', 'sessions')
# 下面都是根据不从的session存储类型, 去获取不同的连接对象, 这个对象就可以存取session
if config['SESSION_TYPE'] == 'redis':
session_interface = RedisSessionInterface(
config['SESSION_REDIS'], config['SESSION_KEY_PREFIX'],
config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
elif config['SESSION_TYPE'] == 'memcached':
session_interface = MemcachedSessionInterface(
config['SESSION_MEMCACHED'], config['SESSION_KEY_PREFIX'],
config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
elif config['SESSION_TYPE'] == 'filesystem':
session_interface = FileSystemSessionInterface(
config['SESSION_FILE_DIR'], config['SESSION_FILE_THRESHOLD'],
config['SESSION_FILE_MODE'], config['SESSION_KEY_PREFIX'],
config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
elif config['SESSION_TYPE'] == 'mongodb':
session_interface = MongoDBSessionInterface(
config['SESSION_MONGODB'], config['SESSION_MONGODB_DB'],
config['SESSION_MONGODB_COLLECT'],
config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'],
config['SESSION_PERMANENT'])
elif config['SESSION_TYPE'] == 'sqlalchemy':
session_interface = SqlAlchemySessionInterface(
app, config['SESSION_SQLALCHEMY'],
config['SESSION_SQLALCHEMY_TABLE'],
config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'],
config['SESSION_PERMANENT'])
else:
session_interface = NullSessionInterface() return session_interface # 返回可能操作数据库中的session的对象
看看能够操作session的对象长什么样子.
def __init__(self, redis, key_prefix, use_signer=False, permanent=True):
if redis is None:
from redis import Redis
redis = Redis()
self.redis = redis # 我配置的redis连接对象, 他就靠这个去连接数据库的
self.key_prefix = key_prefix # 定义的session key的前缀
self.use_signer = use_signer
self.permanent = permanent
上面说了, flask操作session的session_interface变成了新的, 这个session_interface中肯定有存取session的方法, 到底是怎么存取的, follow me.
存放session, key就是 前缀:uuid4

def save_session(self, app, session, response):
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
if not session:
if session.modified:
self.redis.delete(self.key_prefix + session.sid) # 1. 先进行删除
response.delete_cookie(app.session_cookie_name,
domain=domain, path=path)
return
httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app)
expires = self.get_expiration_time(app, session)
val = self.serializer.dumps(dict(session))
self.redis.setex(name=self.key_prefix + session.sid, value=val, # 2. 在进行设置
time=total_seconds(app.permanent_session_lifetime))
if self.use_signer:
session_id = self._get_signer(app).sign(want_bytes(session.sid))
else:
session_id = session.sid
response.set_cookie(app.session_cookie_name, session_id,
expires=expires, httponly=httponly,
domain=domain, path=path, secure=secure)
获取session, 根据用于请求时携带的session, 获取Redis种的数据
def open_session(self, app, request):
sid = request.cookies.get(app.session_cookie_name) # 1.从cookie中获取存放在浏览器的session
if not sid:
sid = self._generate_sid()
return self.session_class(sid=sid, permanent=self.permanent)
if self.use_signer:
signer = self._get_signer(app)
if signer is None:
return None
try:
sid_as_bytes = signer.unsign(sid)
sid = sid_as_bytes.decode()
except BadSignature:
sid = self._generate_sid()
return self.session_class(sid=sid, permanent=self.permanent) if not PY2 and not isinstance(sid, text_type):
sid = sid.decode('utf-8', 'strict')
val = self.redis.get(self.key_prefix + sid) # 2. 从redis中获取 前缀 + session 的值, 这个值就是你使用session["user"] = user, 存的值
if val is not None: # 3. 判断获取结果
try:
data = self.serializer.loads(val) # 4. 取获取到的结果进行反序列化, 得到session中的数据
return self.session_class(data, sid=sid)
except:
return self.session_class(sid=sid, permanent=self.permanent)
return self.session_class(sid=sid, permanent=self.permanent)
到此为止就是flask_session的工作流程
flask_session的应用
下面是我做的一个完成的应用
from flask import Flask, session, request, render_template, redirect
from flask import views
from flask_session import Session
import redis
from datetime import timedelta # 当时使用了Session, 小写的flask原生的session依然需要导入, 因为设置session还是通过这个, 只不过存储session的方式改变了 app = Flask(__name__)
app.config["SESSION_TYPE"] = 'redis' # 指定session存储的类型
app.config["SESSION_REDIS"] = redis.Redis(host="192.168.233.128", port=6379) # 创建redis连接
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=1) # 执行session的有效时间
Session(app) # 使用Session对session的存储机制重新定义 @app.before_request
def confirm():
"""
校验用户是否已经登录
:return:
"""
if session.get("user") or request.path == "/login":
return None
else:
return redirect('/login') class LoginView(views.MethodView):
def get(self):
return render_template("login.html") def post(self):
u = request.form.get("username")
p = request.form.get("password")
if p == "wang": # 当用户登陆成功后, 在session中设置一个标识, 标识用户已经登录了
session["user"] = u
return "登录成功"
else:
return "error" @app.route('/index', endpoint="index")
def index():
return "index" app.add_url_rule("/login", view_func=LoginView.as_view("login")) if __name__ == '__main__':
app.run(host="192.168.12.29", port=80, debug=True)
Flask第三方组件之flask_session的更多相关文章
- Flask第三方组件 之 Flask-Session
原生session:交由客户端保管机制,安全性相对较差,优势是一点都不占用服务器空间 Flask-Session: 解决原生session的劣势 安装包 from flask import Flask ...
- 4.flask第三方组件
1.flask-session的使用 在flask中,有一个app.session_interface = SecureCookieSessionInterface(),也就是存session,调用o ...
- Flask第三方工具组件介绍
flask-wtf组件flask-login组件flask-session组件flask-sqlalchemy组件flask-script组件flask-cache组件flask-assets组件fl ...
- Flask框架 之 第三方组件
浏览目录 flask-session flask-sqlalchemy flask-script flask-migrate flask-session 安装 pip3 install flask-s ...
- Flask框架 (四)—— 请求上下文源码分析、g对象、第三方插件(flask_session、flask_script、wtforms)、信号
Flask框架 (四)—— 请求上下文源码分析.g对象.第三方插件(flask_session.flask_script.wtforms).信号 目录 请求上下文源码分析.g对象.第三方插件(flas ...
- flask seesion组件
一.简介 flask中session组件可分为内置的session组件还有第三方flask-session组件,内置的session组件功能单一,而第三方的flask-sessoin可支持re ...
- 1.7 flask 的组件 wtfroms使用
2019-1-7 17:59:37 还有两天左右flask就结束啦!昨晚逛了一下吾爱破解还有慕课,发现有三个意外项目, Django生鲜项目,flask电影网站项目,vue美团网项目,都保存百度云啦, ...
- C#通过第三方组件生成二维码(QR Code)和条形码(Bar Code)
用C#如何生成二维码,我们可以通过现有的第三方dll直接来实现,下面列出几种不同的生成方法: 1):通过QrCodeNet(Gma.QrCodeNet.Encoding.dll)来实现 1.1):首先 ...
- .Net开发笔记(二十)创建一个需要授权的第三方组件
在使用需要授权的软件时,注册付费的目标是软件的使用者,我们开发人员平时用到的一些第三方组件也是需要授权付费的,也就是说,付费者是开发人员,并不是系统(使用了该第三方组件)的最终使用者. 以上两者的区别 ...
随机推荐
- 在Ubuntu14.10中部署Hadoop2.6.0单节点伪分布集群
1. 环境信息如下: ubuntu:14.10 jdk:openjdk-1.7.0 hadoop:2.6.0 2. 下载hadoop2.6.0, http://apache.fayea.com/had ...
- git下的团队合作模型及git基础知识汇集
https://www.atlassian.com/git/tutorials/syncing/git-fetch Syncing svn使用单个中央库来作为开发者之间沟通的桥梁,而协同合作是通过在开 ...
- IOS生成同时支持armv7,armv7s,i386的静态库.a文件
许多第三方提供的.a文件(一般是那些SDK),嵌入到我们的xcode项目后,生成不会报错. 一部分粗心的SDK提供方,或者我们自己做的.a文件,就会有报错,常见的就是不是armv7结构,或者不是arm ...
- 证书制作 z
一.WCF中的安全方式 说到安全就会涉及到认证,消息一致性和机密性,WCF的安全方式分为两种,即传输安全和消息安全. 传输安全和消息安全的区别:传输安全提供点对点的安全: 比如 A 提供服务,B和C直 ...
- 【Leetcode】【Medium】Search a 2D Matrix
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...
- 【Leetcode】【Medium】Repeated DNA Sequences
All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...
- angular2 遗留问题
1.angular build [2017-07-26] a.改写js/css的引用目录的前缀(比如统一增加 /abc/xxx/*.js) b.build时,可以控制index/js/css的生成 ...
- Spring学习之-各注解的含义总结
注解配置 @ComponentScan("spittr.web"):/在加载Spring上下文时,会扫描spittr.web包查找组件 @ComponentScan注解扫描的组件有 ...
- Latex 参考文献引用
转:http://blog.sina.com.cn/s/blog_4b164557010143tl.html 导入 \usepackage[option]{natbib} 具体的 option 有 r ...
- 【[HNOI2004]L语言】
\(Trie\)树+\(DP\) 我们只需要做一个存在性dp就好了 对于每一个字符串,我们设\(f[i]\)表示从\(1\)到\(i\)位是否能被完全匹配 首先\(f[0]=1\),之后我们对于每一个 ...