zoukankan      html  css  js  c++  java
  • Flask中的session ,自定义实现 session机制, 和 flask-session组件

    session 是基于cookie实现, 保存在服务端的键值对(形式为 {随机字符串:‘xxxxxx’}), 同时在浏览器中的cookie中也对应一相同的随机字符串,用来再次请求的 时候验证;

        注意 :Flask中的session是存在浏览器中  默认key是session(加密的cookie), 也可以像Django一样基于上述的方式实现保存在数据库
    

    1 flask中 session的基本概念

    flask 有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥

        同 reqeust 一样 session 基于上下文管理
    

    本质是字典,具有字典的操作方法

        设置:session['username'] = 'xxx'
        删除:session.pop('username', None)
    

    大概流程:

    第一次请求进来 会把session所有的值都放入内存,对session的增删改查的操作都是在内存中进行的;
    
        class SecureCookieSessionInterface(SessionInterface):
    
            open_session --> 打开,获取 app.session_cookie_name获取加密的session(没有的话会创建)
                                          然后进行解密
    
            save_session  --> 对操作完的sesison进行加密 保存
    

    session的超时时间如何配置:

        app.config['SESSION_COOKIE_NAME'] = ''
    
        'SESSION_COOKIE_NAME':                  'session',    # 默认
        'SESSION_COOKIE_DOMAIN':                None,
        'SESSION_COOKIE_PATH':                  None,
        'SESSION_COOKIE_HTTPONLY':              True,
        'SESSION_COOKIE_SECURE':                False,
        'SESSION_REFRESH_EACH_REQUEST':         True,
        'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
    

    2 flask中 session的流程详解




    刚进来创建 request_context 对象(request,初始化session(最开始为空))-->>

    当接收到用户请求之后,会调用 Flask对象的 session_interface对象的open_session方法,以此来获取一个session对象。-->>

    数据返回给用户,并且把内容中的session重新保存-->>


    3 自定义session

    根据内置session原理可以进行session的定制:

        import uuid
        import json
        from flask.sessions import SessionInterface
        from flask.sessions import SessionMixin
        from itsdangerous import Signer, BadSignature, want_bytes
    
        class MySession(dict, SessionMixin):
            def __init__(self, initial=None, sid=None):
                self.sid = sid
                self.initial = initial
                super(MySession, self).__init__(initial or ())
    
            def __setitem__(self, key, value):
                super(MySession, self).__setitem__(key, value)
    
            def __getitem__(self, item):
                return super(MySession, self).__getitem__(item)
    
            def __delitem__(self, key):
                super(MySession, self).__delitem__(key)
    

        class MySessionInterface(SessionInterface):
            session_class = MySession
            container = {}
    
            def __init__(self):
                import redis
                self.redis = redis.Redis()
    
            def _generate_sid(self):
                return str(uuid.uuid4())
    
            def _get_signer(self, app):
                if not app.secret_key:
                    return None
                return Signer(app.secret_key, salt='flask-session',
                              key_derivation='hmac')
    
            def open_session(self, app, request):
                """
                程序刚启动时执行,需要返回一个session对象
                """
                sid = request.cookies.get(app.session_cookie_name)
                if not sid:
                    sid = self._generate_sid()
                    return self.session_class(sid=sid)
    
                signer = self._get_signer(app)
                try:
                    sid_as_bytes = signer.unsign(sid)
                    sid = sid_as_bytes.decode()
                except BadSignature:
                    sid = self._generate_sid()
                    return self.session_class(sid=sid)
    
                # session保存在redis中
                # val = self.redis.get(sid)
                # session保存在内存中
                val = self.container.get(sid)
    
                if val is not None:
                    try:
                        data = json.loads(val)
                        return self.session_class(data, sid=sid)
                    except:
                        return self.session_class(sid=sid)
                return self.session_class(sid=sid)
    
            def save_session(self, app, session, response):
                """
                程序结束前执行,可以保存session中所有的值
                如:
                    保存到resit
                    写入到用户cookie
                """
                domain = self.get_cookie_domain(app)
                path = self.get_cookie_path(app)
                httponly = self.get_cookie_httponly(app)
                secure = self.get_cookie_secure(app)
                expires = self.get_expiration_time(app, session)
    
                val = json.dumps(dict(session))
    
                # session保存在redis中
                # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
                # session保存在内存中
                self.container.setdefault(session.sid, val)
    
                session_id = self._get_signer(app).sign(want_bytes(session.sid))
    
                response.set_cookie(app.session_cookie_name, session_id,
                                    expires=expires, httponly=httponly,
                                    domain=domain, path=path, secure=secure)
    

        使用时,需要先新进行配置:
        from flask import Flask
        from flask import session
        from pro_flask.utils.session import MySessionInterface
    
        app = Flask(__name__)
    
        app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
        app.session_interface = MySessionInterface()
    
    
        @app.route('/login.html', methods=['GET', "POST"])
        def login():
            print(session)
            session['user1'] = 'alex'
            session['user2'] = 'alex'
            del session['user2']
    
            return "内容"
    
    
        if __name__ == '__main__':
            app.run()
    

    4 flask-session组件


    flask内置session使用签名cookie保存

    flask-session 组件则将支持session保存到多个地方:

    redis:
    memcached
    filesystem
    mongodb
    sqlalchmey:拿数据存到数据库表里面
    
    
    安装
    
    pip3 install flask-session
    

    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()
    

    memcached

    import redis
    from flask import Flask, session
    from flask_session import Session
    import memcache
    
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'xxxx'
    
    
    app.config['SESSION_TYPE'] = 'memcached' 
    app.config['SESSION_PERMANENT'] = True # 如果设置为True,则关闭浏览器session就失效。
    app.config['SESSION_USE_SIGNER'] = False # 是否对发送到浏览器上session的cookie值进行加密
    app.config['SESSION_KEY_PREFIX'] = 'session:' # 保存到session中的值的前缀
    app.config['SESSION_MEMCACHED'] = memcache.Client(['10.211.55.4:12000'])
    
    
    Session(app)
    
    
    @app.route('/index')
    def index():
        session['k1'] = 'v1'
        return 'xx'
    
    
    if __name__ == '__main__':
        app.run()
    

    filesystem

    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'] = 'filesystem'  
    app.config[
        'SESSION_FILE_DIR'] = '/Users/wupeiqi/PycharmProjects/grocery/96.Flask新课程/组件/2.flask-session'  # session类型为redis
    app.config['SESSION_FILE_THRESHOLD'] = 500  # 存储session的个数如果大于这个值时,就要开始进行删除了
    app.config['SESSION_FILE_MODE'] = 384  # 文件权限类型
    
    app.config['SESSION_PERMANENT'] = True  # 如果设置为True,则关闭浏览器session就失效。
    app.config['SESSION_USE_SIGNER'] = False  # 是否对发送到浏览器上session的cookie值进行加密
    app.config['SESSION_KEY_PREFIX'] = 'session:'  # 保存到session中的值的前缀
    
    Session(app)
    
    
    @app.route('/index')
    def index():
        session['k1'] = 'v1'
        session['k2'] = 'v1'
        return 'xx'
    
    
    if __name__ == '__main__':
        app.run()
    

    mongodb

    from flask import Flask, session
    from flask_session import Session
    import pymongo
    
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'xxxx'
    
    app.config['SESSION_TYPE'] = 'mongodb'  
    
    app.config['SESSION_MONGODB'] = pymongo.MongoClient()
    app.config['SESSION_MONGODB_DB'] = 'mongo的db名称(数据库名称)'
    app.config['SESSION_MONGODB_COLLECT'] = 'mongo的collect名称(表名称)'
    
    app.config['SESSION_PERMANENT'] = True  # 如果设置为True,则关闭浏览器session就失效。
    app.config['SESSION_USE_SIGNER'] = False  # 是否对发送到浏览器上session的cookie值进行加密
    app.config['SESSION_KEY_PREFIX'] = 'session:'  # 保存到session中的值的前缀
    
    Session(app)
    
    
    @app.route('/index')
    def index():
        session['k1'] = 'v1'
        session['k2'] = 'v1'
        return 'xx'
    
    
    if __name__ == '__main__':
        app.run()
    

    sqlalchemy

    import redis
    from flask import Flask, session
    from flask_session import Session as FSession
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'xxxx'
    
    # 设置数据库链接
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123@127.0.0.1:3306/fssa?charset=utf8'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    
    # 实例化SQLAlchemy
    db = SQLAlchemy(app)
    
    app.config['SESSION_TYPE'] = 'sqlalchemy'  # session类型为sqlalchemy
    app.config['SESSION_SQLALCHEMY'] = db # SQLAlchemy对象
    app.config['SESSION_SQLALCHEMY_TABLE'] = 'session' # session要保存的表名称
    app.config['SESSION_PERMANENT'] = True  # 如果设置为True,则关闭浏览器session就失效。
    app.config['SESSION_USE_SIGNER'] = False  # 是否对发送到浏览器上session的cookie值进行加密
    app.config['SESSION_KEY_PREFIX'] = 'session:'  # 保存到session中的值的前缀
    FSession(app)
    
    
    @app.route('/index')
    def index():
    
        session['k1'] = 'v1'
        session['k2'] = 'v1'
    
        return 'xx'
    
    
    if __name__ == '__main__':
        app.run()
    

        应用程序比较小,用原生的加密ccokie 保存session(内置)
        应用程序比较大,可以用redis(flask-session)
  • 相关阅读:
    利用DTrace实时检测MySQl
    改进MySQL Order By Rand()的低效率
    RDS for MySQL查询缓存 (Query Cache) 的设置和使用
    RDS For MySQL 字符集相关说明
    RDS for MySQL 通过 mysqlbinlog 查看 binlog 乱码
    RDS for MySQL Mysqldump 常见问题和处理
    RDS for MySQL Online DDL 使用
    RDS MySQL 表上 Metadata lock 的产生和处理
    RDS for MySQL 如何使用 Percona Toolkit
    北京已成为投融资诈骗重灾区:存好骗子公司黑名单,谨防上当!
  • 原文地址:https://www.cnblogs.com/big-handsome-guy/p/8550310.html
Copyright © 2011-2022 走看看