はじめに
The FOSUserBundle, developed by the Symfony community, adds support for a database-backed user system in Symfony. It also handles common tasks like user registration and forgotten password functionality.
FOSUserBundleはSymfonyコミュニティにより開発されており
データベースを使用したユーザ管理システムを提供します。
ユーザ登録やパスワードのリセットなどのよくある機能が実装されています。
Symfonyのインストール時にデフォルトでは入りませんが
ドキュメントがSymfony.com以下にあったり
上記のような記載がベストプラクティスに載っていたりと、信頼できそうです。
基本的な機能や気になったところをまとめます。
セキュリティに関わることなので、内容を鵜呑みにはしないでください。
環境
Symfonyが動作し、Doctrine経由でMySQLにアクセスできることが前提です。
ソフト | バージョン |
---|---|
PHP | 7系 |
Symfony | 3系 |
MySQL | 5.6.x |
Doctrine | 2.5.3 |
(バージョン情報の記憶が曖昧なため、後日追記)
導入
インストール
ドキュメントのInstallationに従います。
作成されるページ
ルーティング
自動で多くのページが生成されます。
機能的にはURLパス見たまんまなので詳細は割愛します。
$ bin/console debug:router | grep fos
fos_user_security_login GET|POST ANY ANY /login
fos_user_security_check POST ANY ANY /login_check
fos_user_security_logout GET|POST ANY ANY /logout
fos_user_profile_show GET ANY ANY /profile/
fos_user_profile_edit GET|POST ANY ANY /profile/edit
fos_user_registration_register GET|POST ANY ANY /register/
fos_user_registration_check_email GET ANY ANY /register/check-email
fos_user_registration_confirm GET ANY ANY /register/confirm/{token}
fos_user_registration_confirmed GET ANY ANY /register/confirmed
fos_user_resetting_request GET ANY ANY /resetting/request
fos_user_resetting_send_email POST ANY ANY /resetting/send-email
fos_user_resetting_check_email GET ANY ANY /resetting/check-email
fos_user_resetting_reset GET|POST ANY ANY /resetting/reset/{token}
fos_user_change_password GET|POST ANY ANY /profile/change-password
ログイン
登録
パスワードリセット
見た目が簡素ですが、もちろんテンプレートの書き換えはできます。
Overriding Default FOSUserBundle Templates
作成されるテーブル
DBには以下のテーブルが生成されます。
mysql> DESC user;
+-----------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(180) | NO | | NULL | |
| username_canonical | varchar(180) | NO | UNI | NULL | |
| email | varchar(180) | NO | | NULL | |
| email_canonical | varchar(180) | NO | UNI | NULL | |
| enabled | tinyint(1) | NO | | NULL | |
| salt | varchar(255) | NO | | NULL | |
| password | varchar(255) | NO | | NULL | |
| last_login | datetime | YES | | NULL | |
| locked | tinyint(1) | NO | | NULL | |
| expired | tinyint(1) | NO | | NULL | |
| expires_at | datetime | YES | | NULL | |
| confirmation_token | varchar(255) | YES | UNI | NULL | |
| password_requested_at | datetime | YES | | NULL | |
| roles | longtext | NO | | NULL | |
| credentials_expired | tinyint(1) | NO | | NULL | |
| credentials_expire_at | datetime | YES | | NULL | |
+-----------------------+--------------+------+-----+---------+----------------+
18 rows in set (0.00 sec)
フィールドごとの役割は以下のとおりです。
ドキュメントに記載が見当たらないので、ソースコードからザッと読んだ内容です。
フィールド | 役割 |
---|---|
id |
ユニークID |
username |
ユーザ名 |
username_canonical |
username をすべて小文字に変換したもの。ユーザ名の重複防止に使用 |
email |
メールアドレス |
email_canonical |
email をすべて小文字に変換したもの。メールアドレスの重複防止に使用 |
enabled |
ログイン可能かを示す。未アクティベートユーザのログイン禁止などに使用 |
salt |
パスワードのハッシュ化に使用されるソルト文字列 |
password |
暗号化されたパスワード |
last_login |
最終ログインの日時 |
locked |
ログイン可能かを示すフラグ。強制的なログイン禁止などに使用 |
expired |
アカウントの有効期限切れを示す。期限が切れているとログイン不可 |
expires_at |
アカウントの有効期限 |
confirmation_token |
パスワードリセットにおける本人確認などに使用されるトークン |
password_requested_at |
ユーザがパスワードリセットをリクエストした日時 |
roles |
アクセスコントロールに使用されるロール |
credentials_expired |
認証情報の有効期限切れを示す。定期的なパスワード変更を促すのに使用 |
credentials_expire_at |
認証情報の有効期限 |
気になったこと
userテーブルに他のフィールドを追加できないのか
必要最低限のフィールドは自動的に作成されましたが
アプリケーションの要件によっては他のフィールドが必要です。
この場合にはエンティティに追加フィールド情報をマッピングできるようです。
例えばアイコン表示用に画像パスを格納したい場合は以下のように記載します。
/**
* @var string
*
* @ORM\Column(name="image_path", type="string", length=255)
*/
protected $image_path;
その後にスキーマを再更新します。
$ bin/console doctrine:schema:update --force
新しくフィールドが追加されているのがわかります。
mysql> DESC user;
+-----------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(180) | NO | | NULL | |
| username_canonical | varchar(180) | NO | UNI | NULL | |
| email | varchar(180) | NO | | NULL | |
| email_canonical | varchar(180) | NO | UNI | NULL | |
| enabled | tinyint(1) | NO | | NULL | |
| salt | varchar(255) | NO | | NULL | |
| password | varchar(255) | NO | | NULL | |
| last_login | datetime | YES | | NULL | |
| locked | tinyint(1) | NO | | NULL | |
| expired | tinyint(1) | NO | | NULL | |
| expires_at | datetime | YES | | NULL | |
| confirmation_token | varchar(255) | YES | UNI | NULL | |
| password_requested_at | datetime | YES | | NULL | |
| roles | longtext | NO | | NULL | |
| credentials_expired | tinyint(1) | NO | | NULL | |
| credentials_expire_at | datetime | YES | | NULL | |
| image_path | varchar(255) | NO | | NULL | |
+-----------------------+--------------+------+-----+---------+----------------+
18 rows in set (0.00 sec)
Userエンティティの基本的な作りは他と変わらないので
リレーションを定義することも同様に可能です。
パスワードのポリシー(長さや使用文字制限)は設定できないのか
内部では、Entity、Form、FormTypeなどが使われているので
それぞれにバリデーションを加えることで実現できそうです。
Overriding Default FOSUserBundle Forms
デフォルトの設定はResources/config/validation.xml
にあるから
使うなら使えばいいし、だめならオーバーライドというスタンスなんでしょうか。
Overriding Default FOSUserBundle Validation
ユーザ名を使わないとログインできないのか
installationでの手順ではユーザ名しか使用できませんでしたが
メールアドレスでのログインも許可できるようです。
security.yml
のid
の部分を変更します。
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
これで、ユーザ名とメールアドレスのどちらかでのログインが可能です。
メールアドレスのみを許すことはできませんが、拡張についてPRがありました。
Added email only authentication
まとめ
デフォルトではセキュリティが割と緩めなので
詳細な設定についてはドキュメントをご一読ください。
全体的に「気になるところはオーバーライドして」というスタンスな気がします。
Webのセキュリティ知識や内部実装への理解は必要ですが
上記のような簡単な手順だけで多くの機能を得られるのはお得ですね。