zoukankan      html  css  js  c++  java
  • Flask-session

    简单说明:

       flask_session可以这么说吧,flask原本的session是保存在浏览器cookie中的,这样就产生了一个很重要的问题,如果我们在session中不存敏感信息还好,如果存的是敏感信息那么信息安全是没有保障的,而flask_session可以让我们把session的值存储在redis/Memcached中。

      将数据存储在redis/memcached中然后把所对应的key存放在用户的cookie中。

    实现方式:

      在flask源码中

    def wsgi_app(self, environ, start_response):
        ctx = self.request_context(environ)
            ctx.push()
            error = None
            try:
                try:
                    response = self.full_dispatch_request()
                except Exception as e:
                    error = e
                    response = self.handle_exception(e)
                except:
                    error = sys.exc_info()[1]
                    raise
                return response(environ, start_response)
            finally:
                if self.should_ignore_error(error):
                    error = None
                ctx.auto_pop(error)
    wsgi_app

    ctx.push()方法中有

    self.session = self.app.open_session(self.request)
    if self.session is None:
        self.session = self.app.make_null_session()
    

     执行的是self.session_interface.open_session(self, request)、

    这里的session_interface是flask中默认的,所以我们如果把默认的session_interface重新赋值那么open_session执行的就不会是flask中默认的session_interface而应该是我们重新赋值的类中的open_session

    RedisSessionInterface源码解析:

        def open_session(self, app, request):
            # 从cookie中拿sid
            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)
            if val is not None:
                try:
                    data = self.serializer.loads(val)
                    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)
    

      可以看到大致是这么做的,

    1.先从cookie中拿值,

    2.判断是否cookie中sid是否存在

    3.1如果不存在那么就返回一个特殊的字典

    3.2如果有sid那么去redis中拿值,并用pickle反序列化,返回一个字典

    当我们在视图函数中进行session操作的时候会调用save_session看看我们接着来看看save_session做了什么事:

     1 def save_session(self, app, session, response):
     2     domain = self.get_cookie_domain(app)
     3     path = self.get_cookie_path(app)
     4 
     5     # Delete case.  If there is no session we bail early.
     6     # If the session was modified to be empty we remove the
     7     # whole cookie.
     8     if not session:
     9        if session.modified:
    10             response.delete_cookie(app.session_cookie_name,
    11                                    domain=domain, path=path)
    12         return
    13 
    14     # Modification case.  There are upsides and downsides to
    15     # emitting a set-cookie header each request.  The behavior
    16     # is controlled by the :meth:`should_set_cookie` method
    17     # which performs a quick check to figure out if the cookie
    18     # should be set or not.  This is controlled by the
    19     # SESSION_REFRESH_EACH_REQUEST config flag as well as
    20     # the permanent flag on the session itself.
    21     if not self.should_set_cookie(app, session):
    22         return
    23 
    24     httponly = self.get_cookie_httponly(app)
    25     secure = self.get_cookie_secure(app)
    26     expires = self.get_expiration_time(app, session)
    27     val = self.get_signing_serializer(app).dumps(dict(session))
    28     response.set_cookie(app.session_cookie_name, val,
    29                         expires=expires, httponly=httponly,
    30                         domain=domain, path=path, secure=secure)

      拿到域名,和路径如果有路径判断是否有修改,此处会出现一个bug就是你在修改数据的时候,程序只会检测到你的第一级数据有没有变化,而不会检测到内部的字典是否发生了变化。

    这时我们可以在views中self.session['modified'] = True

    但是我们更加推荐另一种方式在配置文件中设置

    SESSION_REFRESH_EACH_REQUEST = True 

    这样有一个好处每次都可以设置session而且可以刷新session的过期时间,在原生的session_interface中还要设置 

    session.permanent = True


    而在我们设置的flask_session中就不用设置了默认为True

  • 相关阅读:
    七、python抽象
    六、python条件、循环及其它语句
    泛型数组
    判断数组是否包含此元素
    数组倒序
    Class字节码文件获取的三种方法
    操作系统的产生
    Java重载的概述
    表设计遵循的三大范式实例
    pyqt5窗体分隔
  • 原文地址:https://www.cnblogs.com/Stay-J/p/8999987.html
Copyright © 2011-2022 走看看