2015-04-29 26 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

相关问题