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
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
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
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)
app default objects session_interface = SecureCookieSessionInterface (), SecureCookieSessionInterface rewrite open_session methods and methods SessionInterface save_session object.
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)
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
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
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 ""
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_
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
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)
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:
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
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 #