簡體   English   中英

使用數據庫存儲會話而不是使用Flask存儲Cookie

[英]Use database to store session instead of Cookie with Flask

我有一個與Flask的python項目。

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

我正在使用Flask.session來存儲用戶的信息(身份驗證狀態,首選項......)

默認Flask的會話行為是將會話存儲在用戶的cookie中,並使用secret_key對此cookie進行secret_key以便用戶無法對其進行更改,但他們可以閱讀它。

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

謝謝 !

這是改編自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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM