[Symfony] FOSUserBundleを使わなくても15分でユーザーログインは実装できる
Symfonyでユーザー管理機能を実装するためのバンドルといえば FOSUserBundle が定番だと思います。
確かに、ユーザー管理に必要な最低限の機能を手早く実装できるという点では便利なバンドルなのですが、後々細かい拡張がしづらいという声も聞きます。
あと、個人的にSymfony2時代にしか使ったことがなかったので、Symfony4にちゃんと対応してるのか?という不安もあったのですが、リリースノート を見ると
Added Symfony 4 compatibility.
とか書かれているので特に心配は要らないっぽいです。
FOSUserBundleを使わずにユーザー管理機能を実装するとなると、色んな処理をゼロから書かないといけなくて面倒そうなイメージですが、実は MakerBundle を使えば意外と手軽に実装できます。
というわけで、今回はFOSUserbundleを使わずにユーザー管理を実装する手順を簡単に解説したいと思います✋
User
クラスを作る
1. MakerBundleを使って一撃で https://symfony.com/doc/current/security.html
こちらの公式ドキュメントの焼き直しですが、MakerBundleを使えば、SecurityBundleの UserInterface
を実装した、Doctrineエンティティとしての User
クラスをコマンド一発で作れます。
$ bin/console make:user
The name of the security user class (e.g. User) [User]:
>
Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]:
>
Enter a property name that will be the unique "display" name for the user (e.g. email, username, uuid) [email]:
>
Will this app need to hash/check user passwords? Choose No if passwords are not needed or will be checked/hashed by some other system (e.g. a single sign-on server).
Does this app need to hash/check user passwords? (yes/no) [yes]:
>
created: src/Entity/User.php
created: src/Repository/UserRepository.php
updated: src/Entity/User.php
updated: config/packages/security.yaml
Success!
Next Steps:
- Review your new App\Entity\User class.
- Use make:entity to add more fields to your User entity and then run make:migration.
- Create a way to authenticate! See https://symfony.com/doc/current/security.html
make:user
コマンドを叩いて、Enterを連打しただけです😇
これで、
-
src/Entity/User.php
- SecurityBundleの
UserInterface
実装済み -
email
プロパティがユーザー識別子
- SecurityBundleの
src/Repository/UserRepository.php
の2ファイルが作られ、以下のように config/packages/security.yaml
にも必要な設定が追記されます。
security:
+ encoders:
+ App\Entity\User:
+ algorithm: auto
+
providers:
- in_memory: { memory: null }
+ # used to reload user from session & other features (e.g. switch_user)
+ app_user_provider:
+ entity:
+ class: App\Entity\User
+ property: email
あとはデータベースをマイグレーションすれば、 User
クラスの作成は完了です!
$ bin/console doctrine:migrations:diff
$ bin/console doctrine:migrations:migrate
2. MakerBundleを使って一撃でログイン機能を作る
https://symfony.com/doc/current/security/form_login_setup.html
またしても公式ドキュメントの焼き直しですが、MakerBundleを使えば、ログイン画面とログイン処理(Authenticator)もコマンド一発で作れます。
$ bin/console make:auth
What style of authentication do you want? [Empty authenticator]:
[0] Empty authenticator
[1] Login form authenticator
> 1
The class name of the authenticator to create (e.g. AppCustomAuthenticator):
> LoginFormAuthenticator
Choose a name for the controller class (e.g. SecurityController) [SecurityController]:
>
Do you want to generate a '/logout' URL? (yes/no) [yes]:
>
created: src/Security/LoginFormAuthenticator.php
updated: config/packages/security.yaml
created: src/Controller/SecurityController.php
created: templates/security/login.html.twig
Success!
Next:
- Customize your new authenticator.
- Finish the redirect "TODO" in the App\Security\LoginFormAuthenticator::onAuthenticationSuccess() method.
- Review & adapt the login template: templates/security/login.html.twig.
これで、
-
src/Controller/SecurityController.php
(/login
と/logout
の2つのルートが実装済み) -
src/Security/LoginFormAuthenticator.php
(AbstractGuardAuthenticator を適切に実装済み) -
templates/security/login.html.twig
(ログイン画面のビュー)
の3ファイルが作られ、以下のように config/packages/security.yaml
にも必要な設定が追記されます。
security:
:
:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: lazy
+ guard:
+ authenticators:
+ - App\Security\LoginFormAuthenticator
+ logout:
+ path: app_logout
+ # where to redirect after logout
+ # target: app_any_route
生成された雛形を修正
コマンド一発で生成された雛形は一箇所だけ修正が必要な内容になっています。
LoginFormAuthenticator
の onAuthenticationSuccess
メソッドの以下の部分です。
ログインに成功したあと、ターゲットパスがない場合にデフォルトでどのURLにリダイレクトさせるかを設定します。
以下の例では、 default_index
というルート名のURLにリダイレクトさせています。
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
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('default_index'));
}
3. アクセス制限を設定する
ここまででユーザーログインの機能は実装できているので、 config/packages/security.yaml
で例えば以下のような感じでアクセス制限を設定すれば、「ログイン画面以外は ROLE_USER
を持ったユーザーでログインしないと見られない」という状態が作れます。
security:
:
:
access_control:
- { path: ^/(login|logout)$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
まとめ
- 現代においては、MakerBundleでユーザーログインに必要な実装がほぼコマンド一発で実装できる!
Discussion