我有一个与Flask的python项目。
我正在使用SQL Alchemy(根据文档的这一页:http://flask.pocoo.org/docs/0.10/patterns/sqlalche)来处理我的数据库操作。
我正在使用Flask.session
来存储用户的信息(身份验证状态,偏好设置......)
默认Flask的会话行为是将会话存储在用户的cookie中,并使用secret_key
对此cookie进行签名,以便用户无法对其进行更改,但他们可以阅读它。
我不喜欢我的用户能够“看到”会话的内容。 Flask是否提供了在ORM(SQLAlchemy)中存储会话内容的内置方法,还是我必须自己实现?
谢谢!
答案 0 :(得分:3)
这是改编自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的属性错误,则表示您使用的是早于2.7的Python版本。在这种情况下,您可以使用此函数替换total_seconds方法:
def total_seconds(td):
return td.days * 60 * 60 * 24 + td.seconds