最近、プロジェクト開発のニーズにより、モバイルクライアントとWebページは、セッション(セッション)が確実に実行できるようにするため、統一されたインターフェースのセットを使用しています。正常であり、さまざまな状況で互換性があるため、SessionID の取得方法を変更できればと考えています。デフォルトでは、すべての Web サイトは HTTP リクエストのヘッダー ヘッダーの Cookie を介して実装され、Cookie で指定された SessionID がサーバー側の対応するデータに関連付けられ、セッション機能が実装されます。
ただし、モバイル クライアントの場合、元の Cookie がサポートされない場合や、プラットフォームのニーズに応じてブロックされる場合があるため、開発では SessionID を識別するためにリクエスト ヘッダー X-Session-Token を追加する必要があります。 Laravel フレームワークでは、セッションの初期化、読み取り、起動はすべて IlluminateSessionMiddlewareStartSession ミドルウェアを通じて実装されます。このミドルウェアには、SessionId を取得し、セッション データを復元するために使用する資格情報をセッション コンポーネントに伝えるための重要なメソッドがあります。
このミドルウェアは app/Http/Kernel.php ファイルの下に登録されます。
ミドルウェアを継承する新しいクラスを作成し、登録場所をapp/Http/Kernel.php以下に置き換えました。元のgetSessionメソッドのソースコードは以下のとおりです。 リーリー
新しいミドルウェアでは、次のように変更しました:リーリー
しかし、トラブルも起こります。 。 。変更後、それをメインの開発ブランチにマージする前に、単体テストを実行する必要があることがよくあります。残念ながら、今回は CSRF コンポーネントがエラーを報告したことが問題です。トークン エラーが発生しました。ここで提供されたトークンは通常のものと変わりません。問題はセッションにあるはずです。
ミドルウェア コードを変更しても、フレームワークにはまったく影響を与えないと言えることに注意してください。実際には、そうではありません。なぜなら、作成したミドルウェア コードを変更しても役に立たないからです。継承されたミドルウェア コードと一致していますが、奇妙なことに、ミドルウェアを元のミドルウェアに戻した後は、この問題は発生しません。
そこで、通常の条件と異常な条件でコードを実行し、重要なポイントにブレークポイントを使用してデバッグしたところ、問題はミドルウェア $sessionHandled の重要な属性にあることがわかりました。この値が false の場合、以前の状況が発生します。重要なのは、ミドルウェアの起動時にハンドル メソッドが使用されるということです。セッション ミドルウェアの場合、ハンドル メソッドのコードの最初の行は次のとおりです。
$this->sessionHandled = true;
興味深い。 。 。
私たちは知っています。 Laravel フレームワークの特徴は IoC コンテナです。IoC コンテナは、フレームワーク内のさまざまなクラスを初期化してさまざまな依存関係の注入を実装し、コンポーネント間の疎結合を確保します。ミドルウェアも例外ではありません。シングルトンと通常のインスタンスの最大の違いは、シングルトンは何度作成しても常に同じであり、インスタンス内のプロパティは初期化されないため、問題がないことを知っておく必要があります。ミドルウェアはシングルトンである必要があり、私が自分で作成したミドルウェアは通常のクラスのインスタンスにすぎません。しかし、何が起こっているのか、そしてその理由を知るためには、自分のアイデアを確認する必要があります (実際、解決策はすでに考えられています。これについては後で説明します)。
そして、問題は一般にミドルウェアの初期化にあるので、元気を出してLaravelのスタートアップコードを詳しく調べなければなりません。ここでの重要なポイントは、IlluminatePipelinePipeline というクラスにあります。
このクラスには、send、through、then という 3 つの重要なメソッドがあります。それでは、すべてを開始する鍵はどこにあるのでしょうか。このクラスは主にフレームワークの複数の起動ステップを連続的に実行するもので、1つ目は処理プロセスに必要なコンポーネント(リクエストとミドルウェア)を初期化し、2つ目はこれらの処理コンポーネント(集合体)で構成されるスタックにリクエストを渡すことです。ミドルウェアやルーティングディスパッチコンポーネントなど)を実行し、最後に処理結果(Response)を返します。
これはLaravelのHttp部分(まあ、本来はKernelですが)の中核とも言えるものです。次に、前述の問題は Pipeline の then メソッドとそれが呼び出す getSlice メソッドにあります。 getSlice メソッドを直接観察すると、このメソッドが処理スタックの生成と Middleware クラスのインスタンス化を担当していることがわかります。メソッド コード全体は次のとおりです。 リーリー
$this->container->make($name) に注目してください。これは、ミドルウェア クラスを初期化することを意味します。これは、シングルトンでない場合、繰り返し new され、以前の属性が失われます。初期化される。
その場合、解決策は明らかで、シングルトンにします。
$this->app->singleton(SessionStart::class); // SessionStart はミドルウェア クラスの名前です
上記では、Laravel のデフォルトのセッションミドルウェアの拡張によって引き起こされるセッション書き込み失敗の問題の全体的な分析を紹介しました。気に入っていただければ幸いです。