flask 自定义session机制

# flask原生session机制,cookie中返回session加密的value


class SecureCookieSessionInterface(SessionInterface):
    """The default session interface that stores sessions in signed cookies
    through the :mod:`itsdangerous` module.
    """
    #: the salt that should be applied on top of the secret key for the
    #: signing of cookie based sessions.
    salt = 'cookie-session'
    #: the hash function to use for the signature.  The default is sha1
    digest_method = staticmethod(hashlib.sha1)
    #: the name of the itsdangerous supported key derivation.  The default
    #: is hmac.
    key_derivation = 'hmac'
    #: A python serializer for the payload.  The default is a compact
    #: JSON derived serializer with support for some extra Python types
    #: such as datetime objects or tuples.
    serializer = session_json_serializer
    session_class = SecureCookieSession

    def get_signing_serializer(self, app):
        if not app.secret_key:
            return None
        signer_kwargs = dict(
            key_derivation=self.key_derivation,
            digest_method=self.digest_method
        )
        return URLSafeTimedSerializer(app.secret_key, salt=self.salt,
                                      serializer=self.serializer,
                                      signer_kwargs=signer_kwargs)

    def open_session(self, app, request):
        s = self.get_signing_serializer(app)
        if s is None:
            return None
        val = request.cookies.get(app.session_cookie_name)
        if not val:
            return self.session_class()
        max_age = total_seconds(app.permanent_session_lifetime)
        try:
            data = s.loads(val, max_age=max_age)
            return self.session_class(data)
        except BadSignature:
            return self.session_class()

    def save_session(self, app, session, response):
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)

        # If the session is modified to be empty, remove the cookie.
        # If the session is empty, return without setting the cookie.
        if not session:
            if session.modified:
                response.delete_cookie(
                    app.session_cookie_name,
                    domain=domain,
                    path=path
                )

            return

        # Add a "Vary: Cookie" header if the session was accessed at all.
        if session.accessed:
            response.vary.add('Cookie')

        if not self.should_set_cookie(app, session):
            return

        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        samesite = self.get_cookie_samesite(app)
        expires = self.get_expiration_time(app, session)
        val = self.get_signing_serializer(app).dumps(dict(session))
        response.set_cookie(
            app.session_cookie_name,
            val,
            expires=expires,
            httponly=httponly,
            domain=domain,
            path=path,
            secure=secure,
            samesite=samesite
        )

定制的flask session机制将session的value与一个随机生成的sid对应可以保存到redis中也可以保存到内存中,并且set_cookie中返回给浏览器的不是session加密后的val了,而是session对应的session_id

#coding=utf-8
import uuid
import json
from flask.sessions import SessionInterface
from flask.sessions import SessionMixin
from itsdangerous import Signer, BadSignature, want_bytes

class MySession(dict, SessionMixin):
    def __init__(self, initial=None, sid=None):
        self.sid = sid
        self.initial = initial
        super(MySession, self).__init__(initial or ())

    def __setitem__(self, key, value):
        super(MySession, self).__setitem__(key, value)

    def __getitem__(self, item):
        return super(MySession, self).__getitem__(item)

    def __delitem__(self, key):
        super(MySession, self).__delitem__(key)

class MySessionInterface(SessionInterface):
        session_class = MySession
        container = {}

        def __init__(self):
            import redis
            self.redis = redis.Redis()

        def _generate_sid(self):
            return str(uuid.uuid4())

        def _get_signer(self, app):
            if not app.secret_key:
                return None
            return Signer(app.secret_key, salt='flask-session',
                          key_derivation='hmac')

        def open_session(self, app, request):
            """
            程序刚启动时执行,需要返回一个session对象
            """
            sid = request.cookies.get(app.session_cookie_name)
            if not sid:
                sid = self._generate_sid()
                return self.session_class(sid=sid)

            signer = self._get_signer(app)
            try:
                sid_as_bytes = signer.unsign(sid)
                sid = sid_as_bytes.decode()
            except BadSignature:
                sid = self._generate_sid()
                return self.session_class(sid=sid)

            # session保存在redis中
            # val = self.redis.get(sid)
            # session保存在内存中
            val = self.container.get(sid)

            if val is not None:
                try:
                    data = json.loads(val)
                    return self.session_class(data, sid=sid)
                except:
                    return self.session_class(sid=sid)
            return self.session_class(sid=sid)

        def save_session(self, app, session, response):
            """
            程序结束前执行,可以保存session中所有的值
            如:
                保存到resit
                写入到用户cookie
            """
            domain = self.get_cookie_domain(app)
            path = self.get_cookie_path(app)
            httponly = self.get_cookie_httponly(app)
            secure = self.get_cookie_secure(app)
            expires = self.get_expiration_time(app, session)

            val = json.dumps(dict(session))

            # session保存在redis中
            # self.redis.setex(name=session.sid, value=val,time=app.permanent_session_lifetime)
            # session保存在内存中
            self.container.setdefault(session.sid, val)

            session_id = self._get_signer(app).sign(want_bytes(session.sid))

            response.set_cookie(app.session_cookie_name, session_id,
                                expires=expires, httponly=httponly,
                                domain=domain, path=path, secure=secure)
#使用时,需要先新进行配置:
from flask import Flask
from flask import session
from pro_flask.utils.session import MySessionInterface

app = Flask(__name__)

app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
app.session_interface = MySessionInterface()


@app.route('/login.html', methods=['GET', "POST"])
def login():
    print(session)
    session['user1'] = 'alex'
    session['user2'] = 'alex'
    del session['user2']

    return "内容"


if __name__ == '__main__':
    app.run()

flask 自定义session机制_第1张图片

 

参考:https://www.cnblogs.com/big-handsome-guy/p/8550310.html

你可能感兴趣的:(flask)