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. Java基础之this关键字的作用

    this关键字主要存在三种应用 1.this调用本类中的属性,也就是说调用类中的成员变量: 2.this调用本类中的其他方法: 3.this调用本类中的其他构造方法,调用时要放在构造方法的首行,否则会 ...

  2. Netty入门1之----认识Netty

      Netty 什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Netty 是一个广泛使用的 Java ...

  3. linux下 signal信号机制的透彻分析与各种实例讲解

    转自:http://blog.sina.com.cn/s/blog_636a55070101vs2d.html 转自:http://blog.csdn.net/tiany524/article/det ...

  4. WAS8.5安装和部署

    刚研究WAS8.5的安装部署,写一些注意事项: 1.下载安装软件 安装器:agent.installer.linux.gtk.x86_64_1.7.2000.20140227_0303 WAS: WA ...

  5. 弃坑pexpect,入坑paramiko

    上文书说到,ssh库pexpect的使用,简直就是个“月亮公主”——满眼全是坑.勉强把程序写好了,跑起来的时候发现了一个新坑,让我不可抗拒的把它弃掉了——经常莫名其妙的连不上服务器!开线程连接14台服 ...

  6. 【转】 url中文乱码问题

    [转自]http://blog.csdn.net/rascalboy520/article/details/2511175 在URL中传递参数,是通过HTTP报头来传递的.并不是类似于通过表单来传递, ...

  7. 1.Jdeveloper打印出完整日志(-Djbo.debugoutput=console)

    有时候在JDeveloper中需要打印出来比较系统和完整的ADF运行时日志 例如,想查看VO当前执行的是哪个View Criteria,运行的完整SQL语句到底如何 以及当前Binding Varia ...

  8. ASP.NET Web API编程——文件上传

    首先分别介绍正确的做法和错误的做法,然后分析他们的不同和错误之处,以便读者在实现此功能时可避开误区 1正确的做法 public class AvaterController : BaseApiCont ...

  9. Spring Boot Web Error Page处理

    spring Boot默认是whitelabel error page. 其实我们可以自己处理,由于时间有限,所以就简单说明一下方法. 首先配置 @Configuration public class ...

  10. centos中java安装跟配置

    安装配置java环境 [root@JxateiLinux src]# Wget  http://download.oracle.com/otn-pub/java/jdk/8u161-b12/2f38c ...