2015-04-29 25 views
0

我有一個與Flask的Python項目。使用數據庫來存儲會話,而不是與燒瓶的Cookie

我正在使用SQL鍊金術(根據此文檔的頁面:http://flask.pocoo.org/docs/0.10/patterns/sqlalche)來處理我的數據庫操作。

我使用Flask.session來存儲用戶的信息(認證身份,喜好,...)

默認瓶的會話行爲是存儲在用戶的Cookie會話,並與簽署這個cookie secret_key讓用戶可以」改變它,但他們可以閱讀它。

我不喜歡我的用戶能夠「看到」會話的內容。 Flask是否提供了將會話內容存儲在ORM(SQLAlchemy)中的內置方式,還是我必須自己實現?

謝謝!

回答

1

它改編自http://flask.pocoo.org/snippets/75/

如果您需要存儲大量會話數據,將數據從cookie移動到服務器是有意義的。在這種情況下,您可能希望使用redis作爲實際會話數據的存儲後端。

以下代碼使用redis實現會話後端。它允許您傳入redis客戶端或連接到localhost上的redis實例。所有的鍵都以一個指定的前綴作爲前綴,默認爲session :.

import pickle 
from datetime import timedelta 
from uuid import uuid4 
from redis import Redis 
from werkzeug.datastructures import CallbackDict 
from flask.sessions import SessionInterface, SessionMixin 


class RedisSession(CallbackDict, SessionMixin): 

    def __init__(self, initial=None, sid=None, new=False): 
     def on_update(self): 
      self.modified = True 
     CallbackDict.__init__(self, initial, on_update) 
     self.sid = sid 
     self.new = new 
     self.modified = False 


class RedisSessionInterface(SessionInterface): 
    serializer = pickle 
    session_class = RedisSession 

    def __init__(self, redis=None, prefix='session:'): 
     if redis is None: 
      redis = Redis() 
     self.redis = redis 
     self.prefix = prefix 

    def generate_sid(self): 
     return str(uuid4()) 

    def get_redis_expiration_time(self, app, session): 
     if session.permanent: 
      return app.permanent_session_lifetime 
     return timedelta(days=1) 

    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, new=True) 
     val = self.redis.get(self.prefix + sid) 
     if val is not None: 
      data = self.serializer.loads(val) 
      return self.session_class(data, sid=sid) 
     return self.session_class(sid=sid, new=True) 

    def save_session(self, app, session, response): 
     domain = self.get_cookie_domain(app) 
     if not session: 
      self.redis.delete(self.prefix + session.sid) 
      if session.modified: 
       response.delete_cookie(app.session_cookie_name, 
             domain=domain) 
      return 
     redis_exp = self.get_redis_expiration_time(app, session) 
     cookie_exp = self.get_expiration_time(app, session) 
     val = self.serializer.dumps(dict(session)) 
     self.redis.setex(self.prefix + session.sid, val, 
         int(redis_exp.total_seconds())) 
     response.set_cookie(app.session_cookie_name, session.sid, 
          expires=cookie_exp, httponly=True, 
          domain=domain) 

這裏是如何來啓用它:

app = Flask(__name__) 
app.session_interface = RedisSessionInterface() 

如果您收到total_seconds丟失就意味着你正在使用Python版本比2.7更舊的屬性錯誤。在這種情況下,您可以使用此函數作爲total_seconds方法的替代方法:

def total_seconds(td): 
    return td.days * 60 * 60 * 24 + td.seconds 
+0

我看到了該片段,但它並未完全回答我的問題。 我不想使用其他數據存儲。我想使用我用於模型的那個。 我知道我會有一些性能問題。但它更加方便。 (這是什麼在PHP中使用,會話的處理與MySQL(在大多數情況下)) – Blusky

相關問題