プラグインに認証を配置したら、ログインできない

Posted by muchag | CakePHP 3.x | 2018-02-25 (日) 18:24:56

せっかく認証機能を乗っけたのに
認証を必要とするページへアクセスできない。 😥

【環境】
CakePHP: 3.5.11
php: 7.1.5
経緯

認証を機能をプラグインの中に実装した。

プレフィックスルーティングを利用している。

その他、原因がハッキリとはしていなので、何を書くべきかがわからない。

エラー

認証機能を実装できたので
喜び勇んでログインしてみたところ
下記のようなエラーが出た。

Error: A route matching “array ( ‘controller’ => ‘Users’, ‘action’ => ‘login’, ‘plugin’ => NULL, ‘prefix’ => ‘admin’, ‘_ext’ => NULL, )” could not be found.
原因

ハッキリとしていないけど、後述試行錯誤の結果
エラーメッセージにある plugin が NULL だからな気がする。

解決

AuthComponent のオプションに loginAction を設定したら動いた。

BackController.php

$this->loadComponent('Auth', [
  'authenticate' => [
    'Form' => [
      'fields' => [
        'username' => 'email',
        'password' => 'password',
      ],
      'userModel' => $model,
    ]
  ],
  'loginAction' => [
    'plugin' => $this->plugin,
    'prefix' => $this->request->getParam('prefix'),
    'controller' => 'Users',
    'action' => 'login',
  ],
  'loginRedirect' => [
    'action' => 'index',
  ],
  'logoutRedirect' => [
    'action' => 'login',
  ],
  'authError' => 'ログインできませんでした。ログインしてください。'
]);
試行錯誤
エラー箇所

スタックを追っかけると、認証処理中にログインアクションかどうかを判定する箇所があって
そこで、loginAction で指定された URL と、リクエストの URL が一致しない、というエラーが出ていた。

ここで考えたのは、
loginAction で指定された URL と、リクエストの URL なんて一致するわけがない!
なんだけど・・・もっと細かく処理を見ればわかるんだろうね~。

プラグイン

エラー内容を見てみると、plugin のところが null になっていたので
試しに、デフォルトの loginAction ではなく、
プラグイン名を足した設定を追加してみた。

するとなんと~!
無事に認証が必要なページを表示できた。 8-P

確認
/vendor/cakephp/cakephp/src/Routing/RouteCollection.php

public function match($url, $context)
{
    // Named routes support optimization.
    if (isset($url['_name'])) {
        $name = $url['_name'];
        unset($url['_name']);
        if (isset($this->_named[$name])) {
            $route = $this->_named[$name];
            $out = $route->match($url + $route->defaults, $context);
            if ($out) {
                return $out;
            }
            throw new MissingRouteException([
                'url' => $name,
                'context' => $context,
                'message' => 'A named route was found for "%s", but matching failed.',
            ]);
        }
        throw new MissingRouteException(['url' => $name, 'context' => $context]);
    }
    if ($url['action'] == 'login') {

      debug($url);
      exit;
    }

    foreach ($this->_getNames($url) as $name) {
        if (empty($this->_routeTable[$name])) {
            continue;
        }
        /* @var \Cake\Routing\Route\Route $route */
        foreach ($this->_routeTable[$name] as $route) {
            $match = $route->match($url, $context);
            if ($match) {
                return strlen($match) > 1 ? trim($match, '/') : $match;
            }
        }
    }
    throw new MissingRouteException(['url' => var_export($url, true), 'context' => $context]);
}

上記のようにデバッグコードを仕込んで見てみると


/src/Routing/RouteCollection.php (line 330)
[
	'plugin' => null,
	'prefix' => 'admin',
	'controller' => 'Users',
	'action' => 'login',
	'_ext' => null
]

/src/Routing/RouteCollection.php (line 330)
[
	'plugin' => 'MyPlugin',
	'prefix' => 'admin',
	'controller' => 'Users',
	'action' => 'login',
	'_ext' => null
]

当たり前だけど、違いはプラグインのところだけ。

CakePHP 3.x | 2018-02-25 (日) 18:24:56 |

コメントはまだありません »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment