セッションとflask_session実装原則(ソースコード解析)

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」を

おすすめ

転載: www.cnblogs.com/fengff/p/12421139.html