Authの罠 ログインできない 前の画面に戻される
cakephpのAuthComponentを使ってみているんですが、これがまた癖が強いです。
変な現象が起きて困ってました。
ログインする→何故か前の画面に戻される
具体的に言うと
/index→users/loginでログインする→/indexに戻される。
どうも原因が分からないのでauth.phpを見てみることに。
まずはredirectメソッドを調べる。
function redirect($url = null) { if (!is_null($url)) { $redir = $url; $this->Session->write('Auth.redirect', $redir); } elseif ($this->Session->check('Auth.redirect')) { $redir = $this->Session->read('Auth.redirect'); $this->Session->delete('Auth.redirect'); if (Router::normalize($redir) == Router::normalize($this->loginAction)) { $redir = $this->loginRedirect; } } else { $redir = $this->loginRedirect; } return Router::normalize($redir); } |
二つ目の分岐elseif ($this->Session->check(‘Auth.redirect’))に行っていることが判明。
$redirは/users/indexが入っているかと思いきや、/indexのみ。/indexはログインページ前のページ。
つまりこいつが/users/indexじゃないのが原因というのが分かった。
ということはSessionに入っているAuth.redirectの値を入れているところを検索。
redirect()メソッド以外でAuth.redirectに書き込みをしている箇所は二つ。
startup()メソッドで書き込みが行われているっぽいです。
問題があるのはここ
if ($loginAction == $url) { if (empty($controller->data) || !isset($controller->data[$this->userModel])) { if (!$this->Session->check('Auth.redirect') && env('HTTP_REFERER')) { $this->Session->write('Auth.redirect', $controller->referer(null, true)); } return false; } |
Auth.redirectにrefererを突っ込んでいる。
リファラーだから、/users/loginに来る前のページ/indexが入る。
つまり、ログイン後のredirectがおかしくなる。
これは一体何をやっている処理なのか考えてみる。
リファラーを取っているということはセッション切れでログインしたときに、セッションが切れる前のページに戻すための処理だろう。
この機能は必要なものなので引数ミスとかではなさそう。
ということは、ここに来るまでの分岐がおかしい。
3番目の分岐はリファラーの有無とセッションチェックを行っているだけ。
2番目の分岐はid,passが入力前かどうかのチェック
1番目の分岐が何やら怪しい。
$loginActionはデフォルトではnull。今回はコントローラーでloginAction=/users/login と指定している。
$urlは コントローラーの$param['url']['url']から取っている。この$param['url']['url']は何者かというといまアクセスしたコントローラーとアクション名とパラメータが入ってくる。ログインページなら/users/loginとなる。
この二つの変数はRouter::normalize()でnormalizeされた後に比較されている。当然同じ値なのでイコールは成立。
これがおかしいのでは??
解決する方法を二つ思いついた。
一つはloginActionを指定しない。
そうすることで$urlと$loginActionの分岐は成立しない。
二つ目はログインページの遷移はログインページ(/users/login)そのものを指定しない。/users/indexのように指定しして/users/loginページにリダイレクトさせる。そうすることによってリファラーが/users/indexになるので正常にログインさせることが出来る。
それにしても、ググってもこの話題はほぼないし、Authを使う人たちはこの現象に困らないのだろうか。
何かポカしてるのかな。
Authの参考
http://www.ideaxidea.com/archives/2009/10/cakephp_auth_component.html
if (!is_null($url)) {
$redir = $url;
$this->Session->write(‘Auth.redirect’, $redir);
} elseif ($this->Session->check(‘Auth.redirect’)) {
$redir = $this->Session->read(‘Auth.redirect’);
$this->Session->delete(‘Auth.redirect’);
if (Router::normalize($redir) == Router::normalize($this->loginAction)) {
$redir = $this->loginRedirect;
}
} else {
$redir = $this->loginRedirect;
}
return Router::normalize($redir);
}
二つ目の分岐elseif ($this->Session->check('Auth.redirect'))に行っていることが判明。
$redirは/users/indexが入っているかと思いきや、/indexのみ。/indexはログインページ前のページ。
つまりこいつが/users/indexじゃないのが原因というのが分かった。
ということはSessionに入っているAuth.redirectの値を入れているところを検索。
redirect()メソッド以外でAuth.redirectに書き込みをしている箇所は二つ。
startup()メソッドで書き込みが行われているっぽいです。
問題があるのはここ
if ($loginAction == $url) { if (empty($controller->data) || !isset($controller->data[$this->userModel])) { if (!$this->Session->check('Auth.redirect') && env('HTTP_REFERER')) { $this->Session->write('Auth.redirect', $controller->referer(null, true)); } return false; } |
Auth.redirectにrefererを突っ込んでいる。
リファラーだから、/users/loginに来る前のページ/indexが入る。
つまり、ログイン後のredirectがおかしくなる。
これは一体何をやっている処理なのか考えてみる。
リファラーを取っているということはセッション切れでログインしたときに、セッションが切れる前のページに戻すための処理だろう。
この機能は必要なものなので引数ミスとかではなさそう。
ということは、ここに来るまでの分岐がおかしい。
3番目の分岐はリファラーの有無とセッションチェックを行っているだけ。
2番目の分岐はid,passが入力前かどうかのチェック
1番目の分岐が何やら怪しい。
$loginActionはデフォルトではnull。今回はコントローラーでloginAction=/users/login と指定している。
$urlは コントローラーの$param['url']['url']から取っている。この$param['url']['url']は何者かというといまアクセスしたコントローラーとアクション名とパラメータが入ってくる。ログインページなら/users/loginとなる。
この二つの変数はRouter::normalize()でnormalizeされた後に比較されている。当然同じ値なのでイコールは成立。
これがおかしいのでは??
解決する方法を二つ思いついた。
一つはloginActionを指定しない。
そうすることで$urlと$loginActionの分岐は成立しない。
二つ目はログインページの遷移はログインページ(/users/login)そのものを指定しない。/users/indexのように指定しして/users/loginページにリダイレクトさせる。そうすることによってリファラーが/users/indexになるので正常にログインさせることが出来る。
それにしても、ググってもこの話題はほぼないし、Authを使う人たちはこの現象に困らないのだろうか。
何かポカしてるのかな。
Authの参考
http://www.ideaxidea.com/archives/2009/10/cakephp_auth_component.html
