Backport(バックポート) #3297
未完了ログインフォームの next_uri に特定の値を渡した場合に500エラーとなる
0%
説明
Overview (現象)¶
ログインフォームには認証後に遷移する URL を引き継ぐために next_uri という名前の hidden フィールドが用意されています。
この next_uri に特定の不正な値を指定した状態でログイン操作を行うと認証成功時に 500 エラーとなります。
なお、next_uri の値の改変は input[type="hidden"] の値を書き換えるか、もしくは、 #3073 の修正以後であれば /member/login?next_uri=XXXXX
のURLパラメーターを与えれば可能です。
prod 環境で表示されるエラーメッセージ
現在、サーバが混み合っているか、メンテナンス中です。 ご迷惑をおかけいたしますが、しばらく時間を空けて再度アクセスしてください。
dev 環境で表示されるエラーメッセージ
500 | Internal Server Error | sfConfigurationException The route "foobar" does not exist.
また、 next_uri の値によっては 500 エラーとはならないが、不自然な挙動をするものもあります。
next_uri の値の例:
next_uri | リダイレクト先 | エラー | 備考 |
---|---|---|---|
foobar |
なし | 500 エラー | リダイレクトできずに500エラー |
foo/bar |
/foo/bar |
404 エラー | エラーだが自然な動作 |
/foo |
/foo (※) |
404 エラー | ※OpenPNE.yml の base_url のパスも消える |
/foo/bar |
/foo/bar (※) |
404 エラー | ※OpenPNE.yml の base_url のパスも消える |
foo/bar/baz |
/foo/bar |
404 エラー | "/baz" の情報がなくなっている |
foo/bar?baz=qux |
/foo/bar/baz/qux |
404 エラー | URLの形式が変わっている |
(空の値) | / |
なし | |
http://example.com |
/ |
なし | |
member_config_image |
/member/image/config |
なし | |
@member_config_image |
/member/image/config |
なし | |
member/image/config |
/member/image |
404 エラー | "/config" の情報がなくなっている |
member/config/image |
/member/config |
なし | 意図とは別のURLへリダイレクトしている |
Causes (原因)¶
※以下では、symfony 内部で利用するための独自のURL形式を 内部URL形式 、ブラウザからアクセスする際のURLに利用されるものを 外部URL形式 と呼びます。(ここでは外部サイトを指す URL のことではありません)
この問題はログイン情報POST時に next_uri の入力をチェックする opValidatorNextUri が routing->findRoute() で 外部URL形式 からルートを探している一方で、ログイン成功後のリダイレクト処理で使われている sfAction::redirect() から呼ばれる sfWebController::genUrl() では 内部URL形式 で next_uri の値を扱っていることにより発生しています。
現行の実装では next_uri の値を生成する opWidgetFormInputHiddenNextUri は、routing->getCurrentInternalUri() としているため 内部URL形式 (かつ :module/:action?parameters..
の形式)の値をフォームに設定しています。
例えば、next_uri=foobar は opValidatorNextUri 内の findRoute() 時点で以下のルーティングルールとマッチするために、バリデーションをパスしています。
array(3) { ["name"]=> string(13) "default_index" ["pattern"]=> string(8) "/:module" ["parameters"]=> array(3) { ["module"]=> string(6) "foobar" ["action"]=> string(5) "index" ["sf_culture"]=> string(5) "ja_JP" } }
一方、sfWebController::genUrl() は foobar
を module_name ではなく route_name と扱ってしまうため、例外が発生します。
The route "foobar" does not exist.
Way to fix (修正内容)¶
(※修正内容が確定したら書き換えてください)
修正方針についての参考情報を記します。
next_uri の役割は、未ログイン状態のユーザーがログイン後に最初にアクセスした URL と同じ URL へ遷移させることであると考えられるため、next_uri の値は 外部URL形式 とするのが自然だと思われます。
一方で、next_uri の役割をユーザーが最初にアクセスした "URL" ではなく "アクション" へ遷移させることと考えれば、 内部URL形式 であっても目的を果たせることになります。しかし、next_uri の値はユーザーが書き換え可能な状態に置かれるものであるため、システム内部で利用するための値を露出させるのはあまり得策ではないとも考えられます。
従って、修正は next_uri を一貫して 外部URL形式 で扱うようにするのがよいのではないかと思います。
next_uri を 内部URL形式 で扱う方針にした場合でも、opValidatorNextUri の修正が必要です。