• Flask快速入门(17) — flask_session


    Flask快速入门(17) — flask_session

    作用:将默认保存的签名cookie中的值,保存到 redis/memcached/file/Mongodb/SQLAlchemy

    安装:pip install flask-session

    使用1:

    from flask import Flask,session
    from flask_session import RedisSessionInterface
    import redis
    app = Flask(__name__)
    conn=redis.Redis(host='127.0.0.1',port=6379)  # 连接redis
    
    # use_signer是否对key签名
    # 如果use_siginer为False,这表示不需要配置app.secret_key
    app.session_interface=RedisSessionInterface(conn,key_prefix='lqz')
    @app.route('/')
    def hello_world():
        session['name']='lqz'
        return 'Hello World!'
    
    if __name__ == '__main__':
        app.run()
    

    我们知道session是从app.session_interface入口。所以要改变存储位置的话,要重写app.session_interface。在这里的RedisSessionInterface重写了open_session(取)和save_session(存)。我们来看看RedisSessionInterface这个类

    class RedisSessionInterface(SessionInterface):
        serializer = pickle
        session_class = RedisSession
        # 实例化参数:redis连接的redis; key_prefix存储的前缀; user_signer是否对key签名,为False则不需要设置secret_key,为True时,需要设置; permanent关闭浏览器是否保存,为Frue保存,为False不保存
        def __init__(self, redis, key_prefix, use_signer=False, permanent=True):
            if redis is None:
                from redis import Redis
                redis = Redis()
            self.redis = redis
            self.key_prefix = key_prefix
            self.use_signer = use_signer
            self.permanent = permanent
            
        def open_session(self, app, request):
            sid = request.cookies.get(app.session_cookie_name)
            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)  # 从redis中取出session
            if val is not None:
                try:
                    data = self.serializer.loads(val)  # 获取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)
    
        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)
                    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))  # 将session序列化放入val中
            # 将session设置到redis,name=前缀+字符串,value=session值
            self.redis.setex(name=self.key_prefix + session.sid, value=val,
                             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)
    

    使用2:

    from flask import Flask,session
    from redis import Redis
    from flask_session import Session
    app = Flask(__name__)
    app.config['SESSION_TYPE'] = 'redis'
    app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379')
    Session(app)
    
    @app.route('/')
    def index():
        session['name'] = 'nick'
        return 'hello'
    
    @app.route('/index')
    def test():
        return session['name']
    
    if __name__ == '__main__':
        app.run()
    

    主要是通过配置SESSION_TYPE源码中进行相应的存储:Session(app)源码

    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)
    

    self.init_app(app)源码:

    def init_app(self, app):
        app.session_interface = self._get_interface(app)  # 在这里重写了session_interface
    

    self._get_interface(app)源码:

    def _get_interface(self, app):
        # 在这里做了一些相关的配置
        config = app.config.copy()
        config.setdefault('SESSION_TYPE', 'null')
        config.setdefault('SESSION_PERMANENT', True)
        config.setdefault('SESSION_USE_SIGNER', False)
        config.setdefault('SESSION_KEY_PREFIX', 'session:')
        config.setdefault('SESSION_REDIS', None)
        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')
    	
        # 通过if...elif...else来判断匹配config['SESSION_TYPE'],再执行相应的session_interface
        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
    

    问题:设置cookie时,如何设定关闭浏览器则cookie失效。

    response.set_cookie('k','v',exipre=None)#这样设置即可
    #在session中设置
    app.session_interface=RedisSessionInterface(conn,key_prefix='lqz',permanent=False)
    #一般不用,我们一般都设置超时时间,多长时间后失效
    

    问题:cookie默认超时时间是多少?如何设置超时时间

    #源码expires = self.get_expiration_time(app, session)
    'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),#这个配置文件控制
    
  • 相关阅读:
    14.1.1 使用InnoDB 表的好处:
    7.5.1 Point-in-Time Recovery Using Event Times 使用Event Times 基于时间点恢复
    7.5 Point-in-Time (Incremental) Recovery Using the Binary Log 使用binay log 基于时间点恢复
    7.4.1 Dumping Data in SQL Format with mysqldump
    7.3.2 Using Backups for Recovery 使用备份用于恢复
    7.3.1 Establishing a Backup Policy
    RR 和RC隔离问题
    mark
    weblogic12
    转一篇对EJB理解的文章
  • 原文地址:https://www.cnblogs.com/863652104kai/p/11708074.html
Copyright © 2020-2023  润新知