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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM