session and flask_session implementation principles (source code parsing)

Flask_session a .session and implementation principles (source code parsing)

https://www.cnblogs.com/cwp-bg/p/10084523.html

1.session use and source code parsing

Copy the code
Copy the code
In addition to the request object, there is a session object. It allows you to store user-specific information across requests. Essentially achieved on the basis of Cookies, 
and Cookies for key signature of the session you want to use, so you need to set up a key secret_key use: . A import the session: Import from the Flask the session . B Setting keys: app. secret_key = 'dsfds' (any string) . C provided the session: the session [ 'username'] = 'Bob' D acquires the session:. the session [ 'username'] . E delete: session.pop ( 'username', None ) Import the Flask Flask from, the session App = the Flask (__ name__) app.debug = True app.secret_key = 'sadsfasdf' @ app.route ( '/') DEF index (): the session [ 'name'] = 'Nick' set # the session return 'home' @ app.route ( '/ Test') DEF Test (): Print (the session [ 'name' __name__ == IF '__main__': app.run () # Three things happen in django, one, generate a random string of 2 to 3 inventory write data back to the browser cookie # database in the flask, he did not, but session is how to achieve? # Generate a key into the cookie, then when the next request by decrypting the cookie, and then assigned to the session # to see us through app.session_interface
Copy the code

 

Source analytic session

According to the principle of the above-mentioned session, to analyze the process mechanisms flask session framework implementation.

Flask object using open_session method and save_session method to open and save session information request after request to create context calls open_session method to obtain user information,

After you perform logic processing method will be called to save the user's information save_session

Copy the code
open_session和save_session
def open_session(self, request): # 调用了app的session_interface对象的方法 return self.session_interface.open_session(self, request) def save_session(self, session, response): return self.session_interface.save_session(self, session, response)
Copy the code

 

 app default objects session_interface = SecureCookieSessionInterface (), SecureCookieSessionInterface rewrite open_session methods and methods SessionInterface save_session object.

Copy the code
SecureCookieSessionInterface class (SessionInterface): 
    Pass 

    DEF open_session (Self, App, Request): 
        # secret_key detecting whether a parameter and returns a signature object 
        S = self.get_signing_serializer (App) 
        IF S None IS: 
            return None 
        # acquired session cookie to information 
        Val = request.cookies.get (app.session_cookie_name) 
        # If this is the first request, returns an empty SecureCookieSession objects, session management properties will be handed over to the request context of 
        IF not Val: 
            return self.session_class () 
        # get session expiration time 
        the max_age = total_seconds (app.permanent_session_lifetime) 
        the try: 
            # session information of the user information decoded  
            data = s.loads (val, max_age = max_age)
            # returns user information session object
            self.session_class return (Data) 
        the except BadSignature: 
            return self.session_class () 

    DEF save_session (Self, App, the session, Response): 
        # Gets domain cookie provided 
        Domain = self.get_cookie_domain (App) 
        # cookie settings get the path 
        path = self.get_cookie_path (App) 
        ... 

        # SESSION_REFRESH_EACH_REQUEST parameters detected 
        IF Not self.should_set_cookie (App, the session): 
            return 
        # SESSION_COOKIE_HTTPONLY return parameters 
        HttpOnly = self.get_cookie_httponly (App) 
        # returns the parameters SESSION_COOKIE_SECURE  
        secure = self.get_cookie_secure (app)
        # return time point of failure 
        expires = self.get_expiration_time (app, session)
        Encrypting the user data # 
        Val = self.get_signing_serializer (App) .dumps (dict (the session)) 
        # Set Cookie 
        response.set_cookie (app.session_cookie_name, Val, 
                            Expires Expires =, = HttpOnly HttpOnly, 
                            Domain = Domain, path = path , secure = secure)
Copy the code

 

 RequestContext request context of a session attribute is SecureCookieSession objects, which can be seen as a dictionary;

Summary: flask default by SecureCookieSessionInterface object management session,

        And a rewriting method open_session save_session method SessionInterface object, after the user data is encrypted and stored in a cookie.

source session execution process 
-save_seesion 
    - response time, the value of the encrypted session enlarged serialized into a cookie, to return to the browser 
-open_session 
    - the request, takes a value from the cookie, reverse solution, generated session object, later view function will be able to directly sessoin
Copy the code

 

 2. flask_session use and source code parsing

Role: the default value stored signature cookie is saved to redis / memcached / file / Mongodb / SQLAlchemy

Installation: pip install flask-session

Copy the code
Copy the code
Import the Flask Flask from, the session 
from flask_session Import RedisSessionInterface 
Import Redis 
App = the Flask (__ name__) 
Conn = # redis.Redis connected Redis (Host = '127.0.0.1', Port = 6379) 

# use_signer whether the signature key 
# is False if use_siginer this means that no configuration app.secret_key 
app.session_interface = RedisSessionInterface (Conn, key_prefix = 'LQZ') 
@ app.route ( '/') 
DEF the hello_world (): 
    the session [ 'name'] = 'LQZ' 
    return 'the Hello ! World ' 

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



Print ( "******************************* ***************** ") 


 # Create a session object 
 from flask_session Import Session 
 # Create an instance of Session 
session = Session ()

# App initialization session object at initialization, i.e. loading configuration 
# __init__.py 
from the Flask Flask Import 
app = the Flask (__ name__) 
session.init_app (app = app) 

# task.py 
from the Flask Import session 

@ app.route ( '/ Test ', Methods = [' the POST ']) 
DEF Test (): 
    Session.get (' User ', None) 
    return ""
Copy the code
Copy the code
import redis
from flask import Flask,request,session
from flask.sessions import SecureCookieSessionInterface
from flask_session import Session

app = Flask(__name__)

# app.session_interface = SecureCookieSessionInterface()
# app.session_interface = RedisSessionInterface()
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.Redis(host='140.143.227.206',port=6379,password='1234')
Session(app)

@app.route('/login')
def login():
    session['user'] = 'alex'
    return 'asdfasfd'

@app.route('/home')
def index():
    print(session.get('user'))

    return '...'


if __name__ == '__main__':
    app.run()
    # app.__call__
    # app.wsgi_
Copy the code

 

Source resolve

We know session from app.session_interface entrance. So to change the storage location, then, to rewrite app.session_interface. Here RedisSessionInterface rewritten open_session (taken) and save_session (memory). Let's look at this class RedisSessionInterface

Copy the code
RedisSessionInterface class (SessionInterface): 
    Serializer = the pickle 
    session_class = RedisSession 
    # instantiation parameters: redis redis connection; key_prefix stored prefix; user_signer whether the signature on the key, there is no need secret_key set to False, when True, the need to set; Permanent Close the browser whether to save, save as Frue, to False does not save 
    DEF __init __ (Self, Redis, key_prefix, use_signer = False, Permanent = True): 
        iF iS Redis None: 
            from Import Redis Redis 
            Redis Redis = () 
        self.redis = Redis 
        = key_prefix self.key_prefix 
        self.use_signer = use_signer 
        self.permanent = Permanent 
        
    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, permanent=self.permanent)
        if self.use_signer:
            signer = self._get_signer(app)
            if signer is None:
                return None
            try:
                sid_as_bytes = signer.unsign(sid)
                sid = sid_as_bytes.decode()
            except BadSignature:
                sid = self._generate_sid()
                return self.session_class(sid=sid, permanent=self.permanent)

        if not PY2 and not isinstance(sid, text_type):
            sid = sid.decode('utf-8', 'strict')
        val = self.redis.get(self.key_prefix + sid)  # 从redis中取出session
        if val is not None:
            try:
                data = self.serializer.loads(val)  # 获取session反序列化值
                return self.session_class(data, sid=sid)
            except:
                return self.session_class(sid=sid, permanent=self.permanent)
        return self.session_class(sid=sid, permanent=self.permanent)

    def save_session(self, app, session, response):
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)
        if not session:
            if session.modified:
                self.redis.delete(self.key_prefix + session.sid)
                response.delete_cookie(app.session_cookie_name,
                                       domain=domain, path=path)
            return
        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        expires = self.get_expiration_time(app, session)
        val = self.serializer.dumps(dict(session))  # 将session序列化放入val中
        # 将session设置到redis,name=前缀+字符串,value=session值
        self.redis.setex(name=self.key_prefix + session.sid, value=val,
                         time=total_seconds(app.permanent_session_lifetime))
        if self.use_signer:
            session_id = self._get_signer(app).sign(want_bytes(session.sid))
        else:
            session_id = session.sid
        response.set_cookie(app.session_cookie_name, session_id,
                            expires=expires, httponly=httponly,
                            domain=domain, path=path, secure=secure)
Copy the code

 Mainly carried out by the respective storage configuration SESSION_TYPE source code: Session (app) Source

def __init__(self, app=None):
    self.app = app
    if app is not None:
        self.init_app(app)

self.init_app (app) Source:

init_app DEF (Self, App): 
    app.session_interface = self._get_interface (App) # rewritten here session_interface

self._get_interface (app) Source:

Copy the code
def _get_interface(self, app):
    # 在这里做了一些相关的配置
    config = app.config.copy()
    config.setdefault('SESSION_TYPE', 'null')
    config.setdefault('SESSION_PERMANENT', True)
    config.setdefault('SESSION_USE_SIGNER', False)
    config.setdefault('SESSION_KEY_PREFIX', 'session:')
    config.setdefault('SESSION_REDIS', None)
    config.setdefault('SESSION_MEMCACHED', None)
    config.setdefault('SESSION_FILE_DIR',
                      os.path.join(os.getcwd(), 'flask_session'))
    config.setdefault('SESSION_FILE_THRESHOLD', 500)
    config.setdefault('SESSION_FILE_MODE', 384)
    config.setdefault('SESSION_MONGODB', None)
    config.setdefault('SESSION_MONGODB_DB', 'flask_session')
    config.setdefault('SESSION_MONGODB_COLLECT', 'sessions')
    config.setdefault('SESSION_SQLALCHEMY', None)
    config.setdefault('SESSION_SQLALCHEMY_TABLE', 'sessions')
    
    # 通过if...elif...else来判断匹配config['SESSION_TYPE'],再执行相应的session_interface
    if config['SESSION_TYPE'] == 'redis':
        session_interface = RedisSessionInterface(
            config['SESSION_REDIS'], config['SESSION_KEY_PREFIX'],
            config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
    elif config['SESSION_TYPE'] == 'memcached':
        session_interface = MemcachedSessionInterface(
            config['SESSION_MEMCACHED'], config['SESSION_KEY_PREFIX'],
            config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
    elif config['SESSION_TYPE'] == 'filesystem':
        session_interface = FileSystemSessionInterface(
            config['SESSION_FILE_DIR'], config['SESSION_FILE_THRESHOLD'],
            config['SESSION_FILE_MODE'], config['SESSION_KEY_PREFIX'],
            config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
    elif config['SESSION_TYPE'] == 'mongodb':
        session_interface = MongoDBSessionInterface(
            config['SESSION_MONGODB'], config['SESSION_MONGODB_DB'],
            config['SESSION_MONGODB_COLLECT'],
            config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'],
            config['SESSION_PERMANENT'])
    elif config['SESSION_TYPE'] == 'sqlalchemy':
        session_interface = SqlAlchemySessionInterface(
            app, config['SESSION_SQLALCHEMY'],
            config['SESSION_SQLALCHEMY_TABLE'],
            config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'],
            config['SESSION_PERMANENT'])
    else:
        session_interface = NullSessionInterface()
    return session_interface
Copy the code

 

Copy the code
Question: set a cookie, close the browser how to set the cookie fails. 
response.set_cookie ( 'k', 'v ', exipre = None) # arranged such to 
# is provided in the session 

app.session_interface = RedisSessionInterface (Conn, key_prefix = 'LQZ', Permanent = False) # generally do not, we generally They are set to timeout, failure how long the problem: cookie default timeout is how much? How to set the timeout # = self.get_expiration_time source Expires (App, the session) 'PERMANENT_SESSION_LIFETIME': timedelta (Days = 31 is), the control configuration file #

Guess you like

Origin www.cnblogs.com/fengff/p/12421139.html