管理者のバックエンドをセキュアにする
管理者のバックエンドのインターフェースは、信頼された人からのみアクセス可能であるべきです。Symfony のセキュリティコンポーネントを使用して、Web サイトをセキュアにします。
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 を使用してください。
Admin エンティティを生成するだけでなく、このコマンドは、認証システムとエンティティのワイヤリングのためのセキュリティ設定を更新します:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
--- i/config/packages/security.yaml
+++ w/config/packages/security.yaml
@@ -5,14 +5,18 @@ security:
         Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
     # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
     providers:
-        users_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)/
             security: false
         main:
             lazy: true
-            provider: users_in_memory
+            provider: app_user_provider
             # activate different ways to authenticate
             # https://symfony.com/doc/current/security.html#the-firewall
    Symfony にパスワードをハッシュ化するのに一番有効なアルゴリズムを選択させましょう(これは時が経つと変更されていくものです)。
マイグレーションを生成して、データベースをmigrateします:
1 2
$ symfony console make:migration
$ symfony console doctrine:migrations:migrate -n
    管理者ユーザーのパスワードを生成する
管理者のアカウントを作成するのに専用のシステムを開発することはないです。ここでは1つの管理者しか用意しませんから。ログインするには admin とハッシュ化されたパスワードが必要になります。
好きなパスワードを選択して、次のコマンドを実行しパスワードをハッシュ化してください:
1
$ symfony console security:hash-password
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Symfony Password Hash Utility
=============================
 Type in your password to be hashed:
 >
 ------------------ ---------------------------------------------------------------------------------------------------
  Key                Value
 ------------------ ---------------------------------------------------------------------------------------------------
  Hasher used        Symfony\Component\PasswordHasher\Hasher\MigratingPasswordHasher
  Password hash      $argon2id$v=19$m=65536,t=4,p=1$BQG+jovPcunctc30xG5PxQ$TiGbx451NKdo+g9vLtfkMy4KjASKSOcnNxjij4gTX1s
 ------------------ ---------------------------------------------------------------------------------------------------
 ! [NOTE] Self-salting hasher used: the hasher generated its own built-in salt.
 [OK] Password hashing 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:security:form-login コマンドを実行しセキュリティ設定を更新し、ログインテンプレートを作成し、 認証システム を作成しましょう:
1
$ symfony console make:security:form-login
    コントローラーを SecurityController  と命名し、 logout URLを生成しましょう(yes)。
このコマンドはセキュリティ設定を更新し生成されるクラスとワイヤリングします:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
--- i/config/packages/security.yaml
+++ w/config/packages/security.yaml
@@ -15,7 +15,15 @@ security:
             security: false
         main:
             lazy: true
-            provider: users_in_memory
+            provider: app_user_provider
+            form_login:
+                login_path: app_login
+                check_path: app_login
+                enable_csrf: true
+            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#the-firewall
    Tip
EasyAdminのルートが admin であることをどうやって覚えていられるでしょうか?( App\Controller\Admin\DashboardController で設定しました) 覚えていられませんよね。そんなときはコントローラファイルを見ることもできますが、次のコマンドでルート名とパスの関連を表示することもできます:
1
$ symfony console debug:router
    認可アクセスコントロールのルールを追加する
セキュリティシステムは2つのパートによって構成されています。 認証 と 認可 です。管理者ユーザーを作成した際に ROLE_ADMIN ロールを与えています。 access_control にルールを追加して、 ROLE_ADMIN ロールを持ったユーザーのみが /admin セクションにアクセスできるようにしましょう:
1 2 3 4 5 6 7 8 9 10 11
--- i/config/packages/security.yaml
+++ w/config/packages/security.yaml
@@ -34,7 +34,7 @@ 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 }
 when@test:
    access_control のルールは正規表現でアクセスを制限します。 /admin から始まる URL にアクセスされると、セキュリティシステムは、ログインしているユーザーが ROLE_ADMIN ロールがあるかチェックします。
ログインフォームで認証する
これで、管理者のバックエンドへのアクセスを試みると、ログインページにリダイレクトされ、ログインとパスワードの入力を促されるはずです:
    admin と先ほど選んだパスワードを使ってログインしてください。 そのまま SQL をコピーしていたなら、そのパスワードの値は admin です。
EasyAdmin は自動的に Symfony の認証システムを検知します:
    "ログアウト" リンクをクリックしてください。これで、管理者のバックエンドはセキュアな状態になります。
Note
make:registration:form コマンドを使えば、より高機能な認証システムを作成することができます。