AuthComponentからの移行

違い

  • このプラグインは意図的に承認を処理しません懸念事項を明確に分離するために、意図的に認可から切り離されましたコンピュータアクセス制御も参照してください。このプラグインは、識別認証のみを処理します。承認のための別のプラグインがあるかもしれません。
  • セッションの自動チェックはありません。セッションから実際のユーザーデータを取得するには、SessionAuthenticatorを使用する必要があります。設定されたセッションキーにデータがあるかどうかセッションをチェックし、それをアイデンティティオブジェクトに入れます。
  • ユーザーデータは、古いAuthComponentを介して使用できなくなりましたが、リクエスト属性を介してアクセスでき、アイデンティティオブジェクトにカプセル化されます。$request->getAttribute('authentication')->getIdentity();。さらに、AuthenticationComponentgetIdentity()またはgetIdentityData()メソッドを利用できます。
  • 認証プロセスのロジックは、認証システムと識別子に分割されました。オーセンティケーターは要求から資格情報を抽出し、識別子は資格情報を検証して一致するユーザーを見つけます。
  • DigestAuthenticateはHttpDigestAuthenticatorに名前が変更されました
  • BasicAuthenticateはHttpBasicAuthenticatorに名前が変更されました
  • This plugin intentionally does not handle authorization. It was decoupled from authorization on purpose for a clear separation of concerns. See also Computer access control. This plugin handles only identification and authentication. We might have another plugin for authorization.
  • There is no automatic checking of the session. To get the actual user data from the session you’ll have to use the SessionAuthenticator. It will check the session if there is data in the configured session key and put it into the identity object.
  • The user data is no longer available through the old AuthComponent but is accessible via a request attribute and encapsulated in an identity object: $request->getAttribute('authentication')->getIdentity();. Addiotnally, you can leverage the AuthenticationComponent getIdentity() or getIdentityData() methods.
  • The logic of the authentication process has been split into authenticators and identifiers. An authenticator will extract the credentials from the request, while identifiers verify the credentials and find the matching user.
  • DigestAuthenticate has been renamed to HttpDigestAuthenticator
  • BasicAuthenticate has been renamed to HttpBasicAuthenticator

類似点

  • 既存の認証アダプターであるForm、Basic、Digestはすべて引き続き存在しますが、オーセンティケーターにリファクタリングされています。
  • All the existing authentication adapters, Form, Basic, Digest are still there but have been refactored into authenticators.

識別子とオーセンティケーター

懸念事項の分離の原則に従って、以前の認証オブジェクトは、個別のオブジェクト、識別子、および認証システムに分割されました。

Following the principle of separation of concerns, the former authentication objects were split into separate objects, identifiers and authenticators.
  • Authenticators 着信要求を受け取り、それから識別資格情報を抽出しようとします。 資格情報が見つかると、ユーザーが配置されている識別子のコレクションに渡されます。 そのため、オーセンティケーターはIdentifierCollectionを最初のコンストラクター引数として受け取ります。
  • Identifiers 識別資格情報をストレージシステムに対して検証します。 例: (ORMテーブル、LDAPなど)、識別されたユーザーデータを返します。
  • Authenticators take the incoming request and try to extract identification credentials from it. If credentials are found, they are passed to a collection of identifiers where the user is located. For that reason authenticators take an IdentifierCollection as first constructor argument.
  • Identifiers verify identification credentials against a storage system. eg. (ORM tables, LDAP etc) and return identified user data.

これにより、必要に応じて識別ロジックを簡単に変更したり、ユーザーデータの複数のソースを使用したりできます。

This makes it easy to change the identification logic as needed or use several sources of user data.

独自の識別子を実装する場合、識別子はIdentifierInterfaceを実装する必要があります。

If you want to implement your own identifiers, your identifier must implement the IdentifierInterface.

認証設定の移行

アプリケーションを移行する最初のステップは、アプリケーションのブートストラップメソッドで認証プラグインをロードすることです:

The first step to migrating your application is to load the authentication plugin in your application’s bootstrap method:
public function bootstrap(): void
{
    parent::bootstrap();
    $this->addPlugin('Authentication');
}

次に、アプリケーションを更新して、認証プロバイダーインターフェイスを実装します。 これにより、AuthenticationMiddlewareは、アプリケーションから認証サービスを取得する方法を認識します:

Then update your application to implement the authentication provider interface. This lets the AuthenticationMiddleware know how to get the authentication service from your application:
// in src/Application.php

// Add the following use statements.
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

// Add the authentication interface.
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
    /**
     * Returns a service provider instance.
     *
     * @param \Psr\Http\Message\ServerRequestInterface $request Request
     * @param \Psr\Http\Message\ResponseInterface $response Response
     * @return \Authentication\AuthenticationServiceInterface
     */
    public function getAuthenticationService(ServerRequestInterface $request) : AuthenticationServiceInterface
    {
        $service = new AuthenticationService();
        // Configure the service. (see below for more details)
        return $service;
    }
}

次に、AuthenticationMiddlewareをアプリケーションに追加します:

Next add the AuthenticationMiddleware to your application:
// in src/Application.php
public function middleware($middlewareQueue)
{
    // Various other middlewares for error handling, routing etc. added here.

    // Add the middleware to the middleware queue
    $middlewareQueue->add(new AuthenticationMiddleware($this));

    return $middlewareQueue;
}

AuthComponentの設定を移行する

AuthComponentからの構成配列は、サービスを構成するときに識別子と認証子に分割する必要があります。 したがって、AuthComponentを次のように構成した場合:

The configuration array from AuthComponent needs to be split into identifiers and authenticators when configuring the service. So when you had your AuthComponent configured this way:
$this->loadComponent('Auth', [
    'authentication' => [
        'Form' => [
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ]
        ]
    ]
]);

次のように構成する必要があります:

You’ll now have to configure it this way:
// Instantiate the service
$service = new AuthenticationService();

// Load identifiers
$service->loadIdentifier('Authentication.Password', [
    'fields' => [
        'username' => 'email',
        'password' => 'password',
    ]
]);

// Load the authenticators
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Authentication.Form');

userModelをカスタマイズした場合は、次の構成を使用できます:

If you have customized the userModel you can use the following configuration:
// Instantiate the service
$service = new AuthenticationService();

// Load identifiers
$service->loadIdentifier('Authentication.Password', [
    'resolver' => [
        'className' => 'Authentication.Orm',
        'userModel' => 'Employees',
    ],
    'fields' => [
        'username' => 'email',
        'password' => 'password',
    ]
]);

以前より少し多くのコードがありますが、認証の処理方法にはより多くの柔軟性があります。

While there is a bit more code than before, you have more flexibility in how your authentication is handled.

ログインアクション

AuthenticationMiddlewareは、オーセンティケーターに基づいてIDのチェックと設定を処理します。 通常、ログイン後、AuthComponentは構成された場所にリダイレクトします。 ログイン成功時にリダイレクトするには、ログインアクションを変更して、新しいID結果を確認します:

The AuthenticationMiddleware will handle checking and setting the identity based on your authenticators. Usually after logging in, AuthComponent would redirect to a configured location. To redirect upon a successful login, change your login action to check the new identity results:
public function login()
{
    $result = $this->Authentication->getResult();

    // regardless of POST or GET, redirect if user is logged in
    if ($result->isValid()) {
        $target = $this->Authentication->getLoginRedirect();
        return $this->redirect($target);
    }

    // display error if user submitted and authentication failed
    if ($this->request->is(['post']) && !$result->isValid()) {
        $this->Flash->error('Invalid username or password');
    }
}

本人確認

ミドルウェアを適用した後、ID要求属性を使用してIDデータを使用できます。 これは、現在使用している$this->Auth->user()呼び出しを置き換えます。 現在のユーザーが認証されていない場合、または提供された資格情報が無効な場合、ID属性はnullになります:

After applying the middleware you can use identity data by using the identity request attribute. This replaces the $this->Auth->user() calls you are using now. If the current user is unauthenticated or if the provided credentials were invalid, the identity attribute will be null:
$user = $request->getAttribute('identity');

認証プロセスの結果の詳細については、リクエストに付属し、認証属性でアクセス可能な結果オブジェクトにアクセスできます:

For more details about the result of the authentication process you can access the result object that also comes with the request and is accessible on the authentication attribute:
$result = $request->getAttribute('authentication')->getResult();
// Boolean if the result is valid
$isValid = $result->isValid();
// A status code
$statusCode = $result->getStatus();
// An array of error messages or data if the identifier provided any
$errors = $result->getErrors();

AuthComponent::setUser()を呼び出していた場所ならどこでも、setIdentity()を使用する必要があります:

Any place you were calling AuthComponent::setUser(), you should now use setIdentity():
// Assume you need to read a user by access token
$user = $this->Users->find('byToken', ['token' => $token])->first();

// Persist the user into configured authenticators.
$this->Authentication->setIdentity($user);

許可/拒否ロジックの移行

AuthComponentと同様に、AuthenticationComponentを使用すると、特定のアクションを簡単に「公開」でき、有効なIDが存在する必要がありません:

Like AuthComponent the AuthenticationComponent makes it easy to make specific actions ‘public’ and not require a valid identity to be present:
// In your controller's beforeFilter method.
$this->Authentication->allowUnauthenticated(['view']);

allowUnauthenticated()を呼び出すたびに、現在のアクションリストが上書きされます。

Each call to allowUnauthenticated() will overwrite the current action list.

認証されていないリダイレクトの移行

デフォルトでは、認証が必要な場合、AuthComponentはユーザーをログインページにリダイレクトします。 対照的に、このプラグインのAuthenticationComponentは、このシナリオでは例外を発生させます。 AuthenticationServiceを構成するときにunauthenticatedRedirectを使用して、この例外をリダイレクトに変換できます。

By default AuthComponent redirects users back to the login page when authentication is required. In contrast, the AuthenticationComponent in this plugin will raise an exception in this scenario. You can convert this exception into a redirect using the unauthenticatedRedirect when configuring the AuthenticationService.

queryParamオプションを使用して、現在のリクエストターゲットURIをクエリパラメータとして渡すこともできます:

You can also pass the current request target URI as a query parameter using the queryParam option:
// In the getAuthenticationService() method of your src/Application.php

$service = new AuthenticationService();

// Configure unauthenticated redirect
$service->setConfig([
    'unauthenticatedRedirect' => '/users/login',
    'queryParam' => 'redirect',
]);

次に、コントローラーのログインメソッドでgetLoginRedirect()を使用して、クエリ文字列パラメーターからリダイレクトターゲットを安全に取得できます:

Then in your controller’s login method you can use getLoginRedirect() to get the redirect target safely from the query string parameter:
public function login()
{
    $result = $this->Authentication->getResult();

    // Regardless of POST or GET, redirect if user is logged in
    if ($result->isValid()) {
        // Use the redirect parameter if present.
        $target = $this->Authentication->getLoginRedirect();
        if (!$target) {
            $target = ['controller' => 'Pages', 'action' => 'display', 'home'];
        }
        return $this->redirect($target);
    }
}

ハッシュアップグレードロジックの移行

アプリケーションがAuthComponentのハッシュアップグレード機能を使用する場合。 AuthenticationServiceを利用することにより、このプラグインでそのロジックを複製できます:

If your application uses AuthComponent’s hash upgrade functionality. You can replicate that logic with this plugin by leveraging the AuthenticationService:
public function login()
{
    $result = $this->Authentication->getResult();

    // regardless of POST or GET, redirect if user is logged in
    if ($result->isValid()) {
        $authService = $this->Authentication->getAuthenticationService();

        // Assuming you are using the `Password` identifier.
        if ($authService->identifiers()->get('Password')->needsPasswordRehash()) {
            // Rehash happens on save.
            $user = $this->Users->get($this->Authentication->getIdentityData('id'));
            $user->password = $this->request->getData('password');
            $this->Users->save($user);
        }

        // Redirect to a logged in page
        return $this->redirect([
            'controller' => 'Pages',
            'action' => 'display',
            'home'
        ]);
    }
}