トップページはこちら

Joomla!のログインについて

ちょっと興味深い現象を発見したので報告。

PC2Mを介してJoomla!を利用したサイトを表示し、トップページなどにあるJoomla!のログインフォームから(正しい)ユーザ名とパスワードを送信すると、漏れなく「サーバが見つからないかDNSエラー」メッセージが拝めます(Joomla! 1.0.12と1.5 Beta 2で確認。なおユーザ名やパスワードが不正な場合、Joomla! 1.0.xはJavaScriptでエラーメッセージを表示しているため、PC2Mを介すと「内容が無いよう」になります)。

先に解決方法を書いときます。PEARのHTTP_Clientの本体ファイル(HTTP/Client.php)をテキストエディタで開いて、冒頭にある以下の行を探し、その先頭のコメント記号(ふたつのスラッシュ)を削除してください。

// define('HTTP_CLIENT_QUIRK_MODE', true);

この変更は、Joomla!サイトを利用しないひとでもやっといたほうがいい鴨。

詳しい説明

Joomla!のこのログインフォームは、自分自身(index.php)にフォームデータをPOSTします。index.phpは、ログインフォームからのポストデータがあれば認証処理を行い、認証が成功すると自分自身(index.php)にリダイレクトします。この現象は、このリダイレクト時のHTTPステータスコードに301 Moved Permanentlyが使用されていることで発生します。

本来のRFC定義では、301や302でリダイレクトする場合、クライアントは元々のリクエストメソッドを変更してはいけないことになってたりします。つまり元々のリクエストメソッドがPOSTなら、それを勝手に変更してGETでリダイレクトしてはいけないということですね(そして、GETとHEAD以外のメソッドでは、ユーザの確認なしに勝手にリダイレクトしてはいけないということにもなってます)。しかし実際は、殆どのユーザエージェントは兎に角GETでリダイレクトしてるわけで。RFC2616では、それ以前の版ではPOSTのりダイレクトを誤って(erroneously)GETに変更するユーザエージェントもあると書かれていた302の注釈は、斯様な現状の説明に変更されていたりするわけですが。

それでは我らがHTTP_Clientタンがどういう動作をするかというと、301の場合は、元々のリクエストメソッドがPOSTならそのままPOSTで(ユーザの確認なしに)リダイレクトするのであります。一応RFC準拠風。しかし厳密には規約違反(笑)。

てなことで、こいつにJoomla!のログインフォームを処理させるとどうなるかと言うと、認証成功後のindex.phpへのリダイレクトは(RFCの本来の定義通り)POSTで行われるわけで。つまりログインフォームのポストデータを再度送信しちゃうわけです。勝手にな(笑)。で、リダイレクト先のindex.phpは、ログインフォームのポストデータがあるので再びこれを処理し、認証が成功すると自分自身にリダイレクトするのだけど、それはPOSTなので…。以下繰り返し。リダイレクトが無限ループに陥るという寸法デスネー。

そして、上で出てきたHTTP_CLIENT_QUIRK_MODEという定数を定義しておくと、HTTP_Clientタンも世間一般のユーザエージェントと同じように、兎に角GETでリダイレクトしてくれるようになるというわけです。定数名にある「QUIRK」は、まあそういう意味らしい。なおHTTP_Clientタンは、302の場合は現状では、この定数定義とは無関係に兎に角GETです。中途半端なRFC準拠だな、おい。

なお、HTTP_ClientはHTTP_Requestのラッパーですがリダイレクトのロジックは独自のもので、ちなみにHTTP_Requestは、300番台のレスポンスは兎に角GETになってます。

なぜ301?

さて一方、Joomla!のこのリダイレクトはなぜ301なのでしょう。ここで意図されている動作は、HTTP/1.1であれば303 See Otherを使用するべきである典型的な例ですが、HTTP/1.0を考慮しても妥当なのは302で、301はステータスコードの意味合いからして適切ではありません。これは、Joomla!におけるリダイレクト処理が一箇所に集約されており(Joomla! 1.0.xではincludes/joomla.phpに書かれたmosRedirect()、1.5 Beta 2ではlibraries/joomla/application/application.phpに書かれたJApplication::redirect())、このログインフォームのリダイレクトもここで処理されているためです。

多くのCMSと同様、Joomla!にも外部リンクの管理機能が備わっています。ここで管理される外部リンクへの遷移は、このリダイレクト処理を経て行われ、このような場合には301が、ステータスコードの意味合い的にも適切ですが、一方302はこのような場合には適切ではないどころか、「302 Google Jacking」とか「Googleハイジャック」と呼ばれる、302についてのGoogleの解釈を悪用してリンク先サイトのトラフィックを盗む手法が知られるようになって以降は、外部リンクに302でリダイレクトしてるヤツは盗っ人に違いないという風潮が出来上がってしまったのでした。

Joomla! 1.0.xと同じコードベースのMambo 4.5.xでも、まったく同様にリダイレクト処理が一元化されていますが、こちらにはステータスコードの明示はありません(302になります)。しかし、Mambo関連のウェブサイトを検索すれば、301に変更すべきという議論やその改変方法が見つかります。Joomla!のこの箇所の改変は、こうした意見を反映したものなのだろうと推測されます。

しかし、前述のように301は、外部リンクへの遷移には適切ですが、ここで見てきたログインフォームの例のように、すべてのりダイレクトについて適切であるというわけではありません。願わくば将来のJoomla!では、外部リンクの場合とそれ以外を分離し、個々のケースで適切なステータスコード(ログインフォームの場合は303、あるいは302)が振られるといいなあ、と外野で勝手に呟いてみるテスト。

追記

300番台のレスポンス時の、世間一般のユーザエージェントの皆さまの動作について補足。Firefox 2は303と307ではRFC定義通りの動作を行う。つまり、307では元のメソッドを変更せず、かつそれがPOSTの場合はポストデータを再送信するか否かの確認ダイアログを表示した上でリダイレクトを行う。IE(笑)。


2007/05/07

トラックバック

このエントリーのトラックバックURL:
http://www.rcdtokyo.com/mt/mt-rcdtokyo5428-tb.cgi/819

コメント

コメントをどうぞ



保存しますか?