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的更多相关文章

  1. Flask第三方组件 之 Flask-Session

    原生session:交由客户端保管机制,安全性相对较差,优势是一点都不占用服务器空间 Flask-Session: 解决原生session的劣势 安装包 from flask import Flask ...

  2. 4.flask第三方组件

    1.flask-session的使用 在flask中,有一个app.session_interface = SecureCookieSessionInterface(),也就是存session,调用o ...

  3. Flask第三方工具组件介绍

    flask-wtf组件flask-login组件flask-session组件flask-sqlalchemy组件flask-script组件flask-cache组件flask-assets组件fl ...

  4. Flask框架 之 第三方组件

    浏览目录 flask-session flask-sqlalchemy flask-script flask-migrate flask-session 安装 pip3 install flask-s ...

  5. Flask框架 (四)—— 请求上下文源码分析、g对象、第三方插件(flask_session、flask_script、wtforms)、信号

    Flask框架 (四)—— 请求上下文源码分析.g对象.第三方插件(flask_session.flask_script.wtforms).信号 目录 请求上下文源码分析.g对象.第三方插件(flas ...

  6. flask seesion组件

    一.简介     flask中session组件可分为内置的session组件还有第三方flask-session组件,内置的session组件功能单一,而第三方的flask-sessoin可支持re ...

  7. 1.7 flask 的组件 wtfroms使用

    2019-1-7 17:59:37 还有两天左右flask就结束啦!昨晚逛了一下吾爱破解还有慕课,发现有三个意外项目, Django生鲜项目,flask电影网站项目,vue美团网项目,都保存百度云啦, ...

  8. C#通过第三方组件生成二维码(QR Code)和条形码(Bar Code)

    用C#如何生成二维码,我们可以通过现有的第三方dll直接来实现,下面列出几种不同的生成方法: 1):通过QrCodeNet(Gma.QrCodeNet.Encoding.dll)来实现 1.1):首先 ...

  9. .Net开发笔记(二十)创建一个需要授权的第三方组件

    在使用需要授权的软件时,注册付费的目标是软件的使用者,我们开发人员平时用到的一些第三方组件也是需要授权付费的,也就是说,付费者是开发人员,并不是系统(使用了该第三方组件)的最终使用者. 以上两者的区别 ...

随机推荐

  1. redis 存取问题

    今天在写短信接口时候,要把验证码存到缓存里面.因为之前别人已经写的有案例,按照之前写的,获取 值.存到数据库,存到redis. 因为有过期时间,需要传过期时间.但是怎么都是不出来... 源码: @Ov ...

  2. tcp三次握手和四次挥手(2)

      背景描述 通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之间的通信.但是这并不具体,因为,真正进行通信的实体是在主机中的进程,是一个主机中的一个进程与另外一个主机中的一个进 ...

  3. Java初学者 编译能通过,但显示有错误,并且不会自动弹出方法的解决方法。

    因为使用了 @Data注解,关于注解的作用尚未深入理解,此处先做一个记录. 解决方法是,添加lombok插件

  4. sqlserver根据条件生成插入语句--单表

    ALTER proc [dbo].[proc_insert] (@tablename varchar(256),@where varchar(max))asbeginset nocount ondec ...

  5. Net编译原理简单

    转载:http://blog.csdn.net/sundacheng1989/article/details/20941893 首先简单说一下计算机软件运行.所谓软件运行,就是一步一步做一些事情.计算 ...

  6. laravel where筛选会判断类型吗?

    laravel where筛选会判断类型吗? laravel where筛选会判断类型吗? laravel where筛选会判断类型吗? 这个说会判断不对,说不会判断也不对. 当字符串'1'和数值1是 ...

  7. web.config如何实现301跳转

    .htaccess的301定向非常简单,那么web.config的301定向又应该怎么实现呢? 先来看下,web.config中的301格式 <?xml version="1.0&qu ...

  8. python UI自动化实战记录九:添加日志

    想知道测试脚本运行到了哪一步,在脚本内关键节点处打日志是一个很好的方法.目前只写最简单的方式,logging相关还需要继续深入. 1  引包,并配置info级别以上的都显示 import loggin ...

  9. char *转string遇到诡异的问题记录

    这个问题的背景是在用libevent的buffer_remove时出现的,写一个伪代码 char buffer[2048] ={0}; string str; int n = buffer_remov ...

  10. xalan\xalan\2.7.2\xercesImpl.jar (系统找不到指定的文件)问题

    本文转自:http://blog.csdn.net/lveliu/article/details/77772828 环境搭建为:maven+tomcat tomcat 8.5.2 以上会出现改问题(包 ...