Re: CakePHP修行 #011 無限リダイレクトに気をつけろ

ログイン画面を作っていくぞ、と(CakePHP修行 #011) | i d e a * i d e aで、ブラウザのエラー画面が出たところで作業が終了しました。

ブラウザのエラーメッセージは英語で「このページは不正なリダイレクトをしています」と書かれています。リダイレクトでこういうことが起きるときは無限リダイレクトが原因だと相場は決まっています

では、UsersControllerのコードを見てみましょう。今回の問題は無限リダイレクトが原因だろうというあたりがついていたので、すぐに原因となるコードが見つかりました。

目次

原因となるコード

UsersController(AppControllerを継承)


function login()
{
// 略:ログイン画面を出す処理
}

function beforeFilter()
{
$this->checkSession();
}

AppController

  function checkSession()
{
if (!$this->Session->check('User'))
{
$this->redirect('/users/login');
exit();
}
}

解説

/users/loginにアクセスされたときにUsersControllerでログイン画面を出そうとしていますが、Usersコントローラーのすべてのアクションの前にbeforeFilterでログインチェックを行って「ログイン画面を表示するURIにリダイレクト」しています。

CakePHPにおけるbeforeFilterは、コントローラーのアクションメソッドが呼ばれる前に自動で呼ばれる関数です。これは、フレームワークでいうところのフィルタチェインに相当します。前処理を共通で行えるのでうまく使えばとても便利です。

今回の問題を一気に説明すると、「ログイン画面を表示するアクション自体が、リダイレクトを伴うログインチェックを行ってしまっている」ので、ログイン画面を出す前にリダイレクトが発生してしまい、肝心のログイン画面がどう頑張っても出ないことになっています。

挙動を解説すると「ログインチェックにひっかかってログインURIへリダイレクトされる→ログインURIへアクセス→ログインチェックにひっかかってログインURIへリダイレクトされる→ログインURIへアクセス→以下無限ループ」になり、ブラウザが無限リダイレクトの異常を感知してエラーを出して止まったのでした。ブラウザのはからいがなければ無限にリダイレクトが続いてしまいます。

よくあるミス

今回の無限リダイレクトは誰でも陥るよくあるミスです。ウェブアプリケーションにおけるログインチェックは多くの箇所でかけることになるので、共通の処理を設定したくなります。しかし今回のように「ログイン画面自身が表示されるときに限って、リダイレクトしない」という例外処理が絡んだ場合は、設計を深くするか、そもそもbeforeFilterを使わずログインが必要なアクションで毎回checkSessionを呼ぶようにするなどの対応が必要です。

今回のツッコミは以上です。

そろそろロジックが複雑になってきたので挫折しないことを祈るばかりです :-)

コメント / トラックバック

コメント / トラックバック 3 件

  1. SDozono より:

    解決方法をまとめておきました。参考までにどうぞ。
    http://cakephp.seesaa.net/article/46199896.html

  2. [...] Re: CakePHP修行 #011 無限リダイレクトに気をつけろ : akiyan.com リダイレクトでこういうことが起きるときは無限リダイレクトが原因だと相場は決まっています。 [...]

  3. [...] » Re: CakePHP修行 #011 無限リダイレクトに気をつけろ : akiyan.com [...]