ステップ 15: 管理者のバックエンドをセキュアにする

5.0 version
Maintained

管理者のバックエンドをセキュアにする

管理者のバックエンドのインターフェースは、信頼された人からのみアクセス可能であるべきです。Symfony のセキュリティコンポーネントを使用して、Web サイトをセキュアにします。

Twig と同様に、セキュリティコンポーネントは既に他の依存パッケージが使用しておりインストールされていますが、明示的に composer.json ファイルに追加しましょう:

1
$ symfony composer req security

User エンティティを定義する

参加者が Web サイトに自分のアカウントを作成することはできないですが、ここでは管理者のために正しく機能する認証システムを作成しましょう。そのために、Webサイトの管理者のユーザーを一つだけ用意します。

最初のステップは、 User エンティティを定義することです。混乱を避けるためにここでは Admin を使います。

Symfony のセキュリティ認証システムで Admin エンティティを使用するためには、password プロパティなどの要件が必要になります。

make:entity ではなく、専用の make:user コマンドを使用して Admin エンティティを作成してください:

1
$ symfony console make:user Admin

インタラクティブな質問に次のように答えてください: 管理者を Doctrine に格納したいので (yes)、 管理者のユニークな表示名を username 、そして各ユーザーがパスワードを1つ持つことに(yes)と。

生成されたクラスには、getRole(), eraseCredentials() メソッドの他にも Symfony の認証システムで必要なものが入っています。

Admin ユーザーにさらにプロパティを追加したければ、 make:entity を使用してください。

EasyAdmin のように __toString() メソッドを追加しましょう:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
--- a/src/Entity/Admin.php
+++ b/src/Entity/Admin.php
@@ -74,6 +74,11 @@ class Admin implements UserInterface
         return $this;
     }

+    public function __toString(): string
+    {
+        return $this->username;
+    }
+
     /**
      * @see UserInterface
      */

Admin エンティティを生成するだけでなく、このコマンドは、認証システムとエンティティのワイヤリングのためのセキュリティ設定を更新します:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
--- a/config/packages/security.yaml
+++ b/config/packages/security.yaml
@@ -1,7 +1,15 @@
 security:
+    encoders:
+        App\Entity\Admin:
+            algorithm: auto
+
     # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
     providers:
-        in_memory: { memory: null }
+        # used to reload user from session & other features (e.g. switch_user)
+        app_user_provider:
+            entity:
+                class: App\Entity\Admin
+                property: username
     firewalls:
         dev:
             pattern: ^/(_(profiler|wdt)|css|images|js)/

Symfony にパスワードをエンコードするのに一番有効なアルゴリズムを選択させましょう(これは時が経つと変更されていくものです)。

マイグレーションを生成して、データベースをmigrateします:

1
2
$ symfony console make:migration
$ symfony console doctrine:migrations:migrate -n

管理者ユーザーのパスワードを生成する

管理者のアカウントを作成するのに専用のシステムを開発することはないです。ここでは1つの管理者しか用意しませんから。ログインするには admin とエンコードされたパスワードが必要になります。

好きなパスワードを選択して、次のコマンドを実行しパスワードをエンコードしてください:

1
$ symfony console security:encode-password
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Symfony Password Encoder Utility
================================

 Type in your password to be encoded:
 >

 ------------------ ---------------------------------------------------------------------------------------------------
  Key                Value
 ------------------ ---------------------------------------------------------------------------------------------------
  Encoder used       Symfony\Component\Security\Core\Encoder\MigratingPasswordEncoder
  Encoded password   $argon2id$v=19$m=65536,t=4,p=1$BQG+jovPcunctc30xG5PxQ$TiGbx451NKdo+g9vLtfkMy4KjASKSOcnNxjij4gTX1s
 ------------------ ---------------------------------------------------------------------------------------------------

 ! [NOTE] Self-salting encoder used: the encoder generated its own built-in salt.


 [OK] Password encoding succeeded

管理者を作成する

次の SQL で管理者ユーザーを追加してください:

1
2
3
$ symfony run psql -c "INSERT INTO admin (id, username, roles, password) \
  VALUES (nextval('admin_id_seq'), 'admin', '[\"ROLE_ADMIN\"]', \
  '\$argon2id\$v=19\$m=65536,t=4,p=1\$BQG+jovPcunctc30xG5PxQ\$TiGbx451NKdo+g9vLtfkMy4KjASKSOcnNxjij4gTX1s')"

パスワードの値の $ 符号は全てエスケープしましょう。

セキュリティ認証を設定する

管理者ユーザーができましたので、管理者のバックエンドをセキュアにすることができます。 Symfony は複数の認証の方法をサポートしていますが、ここでは、昔から人気のある フォーム認証システム を使いましょう。

make:auth コマンドを実行しセキュリティ設定を更新し、ログインテンプレートを作成し、 認証システム を作成しましょう:

1
$ symfony console make:auth

1 を選択し、ログインフォーム認証システムを生成し、 AppAuthenticator とし、コントローラーを SecurityController と命名し、 logout URLを生成しましょう(yes)。

このコマンドはセキュリティ設定を更新し生成されるクラスとワイヤリングします:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
--- a/config/packages/security.yaml
+++ b/config/packages/security.yaml
@@ -16,6 +16,13 @@ security:
             security: false
         main:
             anonymous: lazy
+            guard:
+                authenticators:
+                    - App\Security\AppAuthenticator
+            logout:
+                path: app_logout
+                # where to redirect after logout
+                # target: app_any_route

             # activate different ways to authenticate
             # https://symfony.com/doc/current/security.html#firewalls-authentication

コマンド出力のヒントにあるように、ログインが成功した際にユーザーをリダイレクトするように onAuthenticationSuccess() メソッドにあるルートをカスタマイズする必要があります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
--- a/src/Security/AppAuthenticator.php
+++ b/src/Security/AppAuthenticator.php
@@ -94,8 +94,7 @@ class AppAuthenticator extends AbstractFormLoginAuthenticator implements Passwor
             return new RedirectResponse($targetPath);
         }

-        // For example : return new RedirectResponse($this->urlGenerator->generate('some_route'));
-        throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
+        return new RedirectResponse($this->urlGenerator->generate('easyadmin'));
     }

     protected function getLoginUrl()

ちなみに

次のコマンドでルート名とパスの関連を表示することができるので、EasyAdmin ルートが easyadmin ということがわかります:

1
$ symfony console debug:router

認可アクセスコントロールのルールを追加する

セキュリティシステムは2つのパートによって構成されています。 認証認可 です。管理者ユーザーを作成した際に ROLE_ADMIN ロールを与えています。 access_control にルールを追加して、 ROLE_ADMIN ロールを持ったユーザーのみが /admin セクションにアクセスできるようにしましょう:

1
2
3
4
5
6
7
8
9
--- a/config/packages/security.yaml
+++ b/config/packages/security.yaml
@@ -33,5 +33,5 @@ security:
     # Easy way to control access for large sections of your site
     # Note: Only the *first* access control that matches will be used
     access_control:
-        # - { path: ^/admin, roles: ROLE_ADMIN }
+        - { path: ^/admin, roles: ROLE_ADMIN }
         # - { path: ^/profile, roles: ROLE_USER }

access_control のルールは正規表現でアクセスを制限します。 /admin から始まる URL にアクセスされると、セキュリティシステムは、ログインしているユーザーが ROLE_ADMIN ロールがあるかチェックします。

ログインフォームで認証する

これで、管理者のバックエンドへのアクセスを試みると、ログインページにリダイレクトされ、ログインとパスワードの入力を促されるはずです:

admin と先ほどエンコードしたパスワードを使ってログインしてください。 そのまま SQL をコピーしていたなら、そのパスワードの値は admin です。

EasyAdmin は自動的に Symfony の認証システムを検知します:

"ログアウト" リンクをクリックしてください。これで、管理者のバックエンドはセキュアな状態になります。

注釈

make:registration:form コマンドを使えば、より高機能な認証システムを作成することができます。


  • « Previous ステップ 14: フォームでフィードバックを受ける
  • Next » ステップ 16: API でスパム対策をする

This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.