Flask_session .sessionと実装の原則(ソースコード解析)
https://www.cnblogs.com/cwp-bg/p/10084523.html
1.session使用とソースコード解析
リクエストオブジェクトに加えて、セッションオブジェクトが存在します。それはあなたが要求にわたってユーザー固有の情報を保存することができます。基本的にクッキーに基づいて達成し、
あなたがキーsecret_keyに設定する必要があるので、使用したいセッションの鍵署名のためにクッキー を使用する: 。Aのインポートセッションを:フラスコからインポートセッション Bキーの設定:アプリを。 SECRET_KEY = 'dsfds'は、(任意の文字列) 。Cは、セッション提供:セッションを[ 'ユーザ名'] = 'ボブ' Dセッション:.セッションを取得[ 'ユーザ名'] E削除します。session.pop( 'ユーザ名'、なし ) フラスコフラスコ、セッションインポート のApp =フラスコを(__ name__) app.debug = Trueの app.secret_key = 'sadsfasdf' @ app.route( '/') DEFインデックス(): セッション[ '名前'] = 'ニックセット#セッション 復帰'ホーム' @ app.route( '/テスト') DEFテスト(): 印刷(セッション[ 'name'を __name__ == IF「__main__」: app.run() #3つのことが、ジャンゴに1を起こる、ブラウザのクッキーに2〜3在庫書き込みデータバックのランダムな文字列を生成し 、フラスコ内の#データベース、彼はしませんでしたが、セッションでは、どのように達成することですか? #時にクッキーを解読することにより、次の要求、その後、クッキーにキーを生成し、その後、セッションに割り当てられた app.session_interfaceを通して私たちを参照してください#
ソース分析セッション
上記セッションの原理によれば、処理機構フラスコセッション・フレームワークの実装を分析します。
コンテキストを作成するために要求した後にオープンし、セッション情報要求の保存にopen_session方法とSAVE_SESSIONメソッドを使用してフラスコのオブジェクトは、ユーザ情報を取得するためにopen_sessionメソッドを呼び出し、
あなたが実行した後、ロジック処理方法は、ユーザーの情報SAVE_SESSIONを保存するために呼び出されます
open_session和SAVE_SESSION
デフopen_session(自己、リクエスト): #调用了アプリ的session_interface对象的方法 リターンself.session_interface.open_session(自己、リクエスト) デフSAVE_SESSION(自己、セッション、応答): リターンself.session_interface.save_session(自己、セッション、応答)
アプリケーションのデフォルトはsession_interface = SecureCookieSessionInterface()、SecureCookieSessionInterface書き換えopen_session方法および方法SessionInterfaceのSAVE_SESSIONオブジェクトをオブジェクト。
SecureCookieSessionInterfaceクラス(SessionInterface): パス DEFのopen_session(セルフ、アプリケーション、要求): #secret_keyに検出するかどうかのパラメータや戻り署名オブジェクト S = self.get_signing_serializer(APP) Sなしていない場合: 戻りなし #取得したセッションクッキーに情報 ヴァル= request.cookies.get(app.session_cookie_name) #これが最初の要求である場合、空のSecureCookieSessionオブジェクトを返し、セッション管理特性が要求コンテキストにハンドオーバされる IFないヴァル: 戻りself.session_class() #GETセッションの有効期限 max_ageの= total_seconds(app.permanent_session_lifetime) の試行: デコードされたユーザー情報の#セッション情報 データ= s.loads(ヴァル、max_ageの= max_ageの) #リターン情報、ユーザー・セッションオブジェクト 戻りself.session_class(データ) BadSignature除く: リターンself.session_class() DEFのSAVE_SESSION(セルフ、アプリケーション、セッション、応答): #取得ドメインクッキーセット ドメイン= self.get_cookie_domain(アプリ) #取得クッキーパスセット のパス= self.get_cookie_path(APP) ... #SESSION_REFRESH_EACH_REQUESTパラメータ検出され ていない場合のself.should_set_cookie(アプリケーション、セッションを): リターン 位SESSION_COOKIE_HTTPONLYパラメータを返す のHttpOnly = self.get_cookie_httponly(APP) #リターンをSESSION_COOKIE_SECUREパラメータは、 確保= self.get_cookie_secure(APP) 失敗の#の復帰時点を 有効期限が切れる= self.get_expiration_time(アプリ、セッション) #ユーザーデータの暗号化 ヴァル= self.get_signing_serializer(APP)は(dictの(セッション)).dumps #設定されたCookieの response.set_cookie(app.session_cookie_name、ヴァルは、 有効期限=、= HttpOnlyのHttpOnlyの、有効期限 のドメインを=ドメイン、パス=パスが確保 =固定)
セッション属性のRequestContextの要求コンテキストは、辞書のように見ることができるSecureCookieSessionオブジェクトです。
概要:フラスコデフォルトSecureCookieSessionInterfaceオブジェクト管理セッションによって、
そして、書き換え方法open_session SAVE_SESSION法SessionInterfaceオブジェクト、ユーザーデータは暗号化され、クッキーに保存された後。
ソースセッションの実行処理 -save_seesion -応答時間、暗号化されたセッションの値がブラウザに戻り、クッキーにシリアライズ拡大 -open_session -要求、クッキーの値をとり、逆溶液、生成されたセッション・オブジェクト後でビュー機能は、直接sessoinできるようになります
2. flask_session使用とソースコード解析
役割:デフォルト値保存された署名CookieがRedisの/ memcachedの/ファイル/ MongoDBの/ SQLAlchemyのに保存されます
インストール:PIPフラスコセッションをインストール
セッションからのインポートフラスコフラスコ flask_sessionインポートRedisSessionInterfaceから のインポートのRedis のApp =フラスコ(__ name__) コネティカット=#redis.Redis接続のRedis(ホスト= '127.0.0.1'、ポート= 6379) 署名鍵かどうか#のuse_signer use_siginer場合#はFalseですこの手段は設定なしapp.secret_keyその app.session_interface = RedisSessionInterface(コネチカット州、key_prefix = 'LQZ') @ app.route( '/') DEF hello_world(): セッション[ '名前'] = 'LQZ' リターン「こんにちは!世界 __main__「__name__ ==場合は、 ': app.runは() 「(印刷******************************* ***************** ") #セッション・オブジェクトを作成 flask_sessionインポートセッションから セッションのインスタンスを作成# )セッション=セッション( 初期化時#アプリの初期化セッション・オブジェクト、即ち装填構成 #1 __init__.py フラスコフラスコインポートから アプリ=フラスコ(__ name__) session.init_app(APP = APP) #task.py フラスコインポートセッションから @ app.route(「/試験'メソッド= [' POST ']) DEF試験(): Session.get('ユーザ」、なし) リターン""
インポートはRedisの フラスコインポートフラスコ要求から、セッション flask.sessionsからはSecureCookieSessionInterfaceをインポート flask_sessionインポートセッションから アプリ=フラスコ(__ name__) #app.session_interface = SecureCookieSessionInterface() #app.session_interface = RedisSessionInterface() App.configファイル[ 'SESSION_TYPE'] = 'Redisの' app.configを[ 'SESSION_REDIS'] = redis.Redis(ホスト= '140.143.227.206'、ポート= 6379、パスワード= '1234') セッション(アプリ) @ app.route( '/ログイン') デフログイン(): セッション[ 'ユーザー'] = 'アレックス' リターン'asdfasfd' @ app.route( '/ home')を DEFインデックス(): プリント(session.get( 'ユーザー')) '...'を返す 場合__name__ == '__main__': app.run() #アプリ.__ call__ #app.wsgi_
ソース決意
私たちは、app.session_interfaceの入り口からセッションを知っています。だから、app.session_interfaceを書き換えるために、そして、保存場所を変更します。ここでRedisSessionInterface書き換えopen_session(とら)とSAVE_SESSION(メモリ)。このクラスRedisSessionInterfaceで見てみましょう
RedisSessionInterfaceクラス(SessionInterface): シリアライザ=ピクルス session_class = RedisSession #インスタンス化パラメータ:RedisのRedisの接続; key_prefixプレフィックス保存され、キーの署名が、Falseに不要のsecret_keyにセットが存在しないuser_signerかどうかTrueの場合、設定する必要があり、常設閉じますFrueとして保存、保存するかどうかのブラウザは、Falseに保存されません :DEF(セルフ、Redisの、key_prefix、use_signer = Falseを、永久=真)__init __ のiFあるのRedisなし: インポートのRedis Redisのから のRedis Redisの=() self.redis = Redisの = key_prefix self.key_prefix self.use_signer = use_signer self.permanent =永久 DEFのopen_session(セルフ、アプリケーション、要求): SID = request.cookies.get(app.session_cookie_name) IFないSID: SID = self._generate_sid() の戻りself.session_class(SID = SID、永久= self.permanent) self.use_signerの場合: 署名者= self._get_signer(アプリ) 署名者がなしの場合: 戻りなしの 試み: sid_as_bytes = signer.unsign( SID) 、SID = sid_as_bytes.decode() BadSignature除く: SID = self._generate_sid() 戻りself.session_class(SID = SID、永久= self.permanent) )ならないPY2としないでisinstance(SID、text_type: SID = SID。デコード( 'UTF-8'、 '厳密') ヴァル= self.redis.get(self.key_prefix + SID)#从Redisの中取出セッション self.redis.delete(self.key_prefix + SESSION.SID) valがNoneでない場合: 試してください: データ= self.serializer.loads(val)で#获取セッション反序列化值 リターンself.session_class(データ、SID = SID) を除い: リターンself.session_class(SID = SID、永久= self.permanent) リターン自己。 session_class(SID = SID、永久= self.permanent) :SAVE_SESSION(自己、アプリケーション、セッション、応答)DEF ドメイン= self.get_cookie_domain(APP) パス= self.get_cookie_path(APP) でない場合、セッション: session.modified場合: ドメイン=ドメイン、パス=パス) リターン response.delete_cookie(app.session_cookie_name、 HttpOnlyの= self.get_cookie_httponly(APP) 確保= self.get_cookie_secure(APP)の 有効期限が切れる= self.get_expiration_time(APP、セッション) のval = self.serializer.dumps(dictの(セッション))#将セッション序列化放入ヴァル中 #将セッション设置到Redisの、名前=前缀+字符串、値=セッション值 self.redis.setex(名= self.key_prefix + SESSION.SID、値= valを、 時間= total_seconds(アプリ。 permanent_session_lifetime)) の場合self.use_signer: SESSION_ID = self._get_signer(アプリ).sign(want_bytes(SESSION.SID)) 他: SESSION_ID = SESSION.SID response.set_cookie(app.session_cookie_name、SESSION_ID、 有効期限が切れる=満了し、HTTPのみ= HttpOnlyの、 ドメイン=ドメイン、パス=パス、セキュア=セキュア)
主に各ストレージ構成SESSION_TYPEソースコードによって行わ:セッション(APP)ソース
デフ__init __(自己、アプリ=なし): self.app =アプリ アプリはNoneではない場合: self.init_app(アプリ)
self.init_app(アプリ)出典:
:DEF(自己、APP)init_app app.session_interface = self._get_interface(APP)ここで書き換え#session_interface
self._get_interface(アプリ)出典:
デフ_get_interface(自己、アプリ): #在这里做了一些相关的配置 コンフィグ= app.config.copy() config.setdefault( 'SESSION_TYPE'、 'ヌル') config.setdefault( 'SESSION_PERMANENT'、true)を 設定。 SetDefault( 'SESSION_USE_SIGNER'、False)が config.setdefault( 'SESSION_KEY_PREFIX'、 'セッション:') config.setdefault( 'SESSION_REDIS'、なし) config.setdefault( 'SESSION_MEMCACHED'、なし) config.setdefault( 'SESSION_FILE_DIR'、 OS .path.join(os.getcwd()、 'flask_session')) config.setdefault( 'SESSION_FILE_THRESHOLD'、500) config.setdefault( 'SESSION_FILE_MODE'、384) 設定。SetDefault( 'SESSION_MONGODB'、なし) config.setdefault( 'SESSION_MONGODB_DB'、 'flask_session') config.setdefault( 'SESSION_MONGODB_COLLECT'、 'セッション') config.setdefault( 'SESSION_SQLALCHEMY'、なし) config.setdefault( 'SESSION_SQLALCHEMY_TABLE'、 'セッション') #を通过場合。 ..elif ...他に来判断匹配設定[ 'SESSION_TYPE']、再执行相应的session_interface かの設定[ 'SESSION_TYPE'] == 'Redisの': session_interface = RedisSessionInterface( 設定[ 'SESSION_REDIS']、コンフィグ[ 'SESSION_KEY_PREFIX ']、 コンフィグ[' SESSION_USE_SIGNER ']は、config [' SESSION_PERMANENT ']) のelifコンフィグ[' SESSION_TYPE '] == 'memcachedの': session_interface = MemcachedSessionInterface( 設定[] 'SESSION_MEMCACHED'は、config [ 'SESSION_KEY_PREFIX']、 コンフィグ[ 'SESSION_USE_SIGNER']は、config [ 'SESSION_PERMANENT']) ELIFコンフィグ[ 'SESSION_TYPE'] == 'ファイルシステム': session_interface = FileSystemSessionInterface( コンフィグ[ 'SESSION_FILE_DIR']は、config [ 'SESSION_FILE_THRESHOLD']、 コンフィグ[ 'SESSION_FILE_MODE']は、config [ 'SESSION_KEY_PREFIX']、 コンフィグ[ 'SESSION_USE_SIGNER' ]は、config [ 'SESSION_PERMANENT']) のelifコンフィグ[ 'SESSION_TYPE'] == 'のMongoDB': session_interface = MongoDBSessionInterface( コンフィグ[ 'SESSION_MONGODB']は、config [ 'SESSION_MONGODB_DB']、 コンフィグ[ 'SESSION_MONGODB_COLLECT']、 のelif設定[' SESSION_TYPE '] =='SQLAlchemyの': session_interface = SqlAlchemySessionInterface( 設定[ 'SESSION_KEY_PREFIX']、コンフィグ[ 'SESSION_USE_SIGNER']、 コンフィグ[ 'SESSION_PERMANENT']) アプリは、config [ 'SESSION_SQLALCHEMY']、 コンフィグ[ 'SESSION_SQLALCHEMY_TABLE']、 コンフィグ[ 'SESSION_KEY_PREFIX']は、config [ 'SESSION_USE_SIGNER']、 コンフィグ[ 'SESSION_PERMANENT']) 他: session_interface = NullSessionInterface() 戻りsession_interface
質問:クッキーを設定し、クッキーが失敗した設定方法ブラウザを閉じます。 response.set_cookie( 'K'、 'V '、exipre =なし)位に配置され、このような #セッションで提供されて
app.session_interface = RedisSessionInterface(コネチカット州、key_prefix = 'LQZ'、常設= False)が #は、一般的ではない、我々一般的に行います彼らがタイムアウトに設定され、障害がどのくらい 問題:クッキーのデフォルトのタイムアウトはどのくらいですか?タイムアウトを設定する方法 #= self.get_expiration_timeソースは(アプリケーション、セッション)有効期限 はtimedelta(日= 31である)、制御設定ファイル番号:「PERMANENT_SESSION_LIFETIME」を