symfony2が主流になって認証系はすべてFOSに絞られてきました。そこでそろそろsynfony1.4から移行するタイミングかなと思います。
方法に関して色々と調べてみると下記のソースにたどり着きます。
- http://qpleple.com/migrate-from-sfguard-to-fosuserbundle/
- https://github.com/FriendsOfSymfony/FOSAdvancedEncoderBundle
- http://www.folliked.com/sf2/migrer-sfdoctrineguardplugin-vers-fosuserbundle
上記ソースで大体可能なのですが多少説明が足りない部分もあるので下記に方法をまとめておきます。
- 1.FOSAdvancedEncoderBundleをインストール(composer.json,AppKernel)
- 2.app/config/config.ymlの編集
- 3.User.php Entityを編集
- 4.MessageDigestPasswordEncoder.phpを作成
- 5.app/config/parameters.ymlの編集
1.FOSAdvancedEncoderBundleをインストール(composer.json,AppKernel)
composer.jsonに追加
"friendsofsymfony/advanced-encoder-bundle": "dev-master"
app/AppKernel.phpに追加
$bundles = array( // ... new FOS\AdvancedEncoderBundle\FOSAdvancedEncoderBundle(), );
2.app/config/config.ymlの編集
http://qpleple.com/migrate-from-sfguard-to-fosuserbundle/
が参考になりました。
fos_advanced_encoder: encoders: default: algorithm: sha512 iterations: 5000 encode_as_base64: true legacy: algorithm: sha1 iterations: 1 encode_as_base64: false
3.User.php Entityを編集
FOSUserBundleを継承しているBundleのEntityを編集します。User class に implements EncoderAwareInterface することを忘れないでください。EncoderAwareInterface implementするとgetEncoderName()が存在しないとエラーが出るのでこちらも注意してください。
// src/App/UserBundle/Entity/User.php use FOS\AdvancedEncoderBundle\Security\Encoder\EncoderAwareInterface; class User implements EncoderAwareInterface { // ... /** * @ORM\Column(name="algorithm", type="string", length=255) */ protected $algorithm = 'sha512'; public function getEncoderName() { return $this->algorithm == 'sha1' ? 'legacy' : 'default'; } public function setSalt($salt) { $this->salt = $salt; } }
編集後に php app/console doctrine:schema:update –force も忘れないでください。
4.MessageDigestPasswordEncoder.phpを作成
FOSUserBundleを継承しているBundleに対して下記のクラスを作成します。下記の例ではAppUserBundleを利用します。src/App/UserBundle/security/MessageDigestPasswordEncoder.phpを作成します。
内容は下記になります
<?php namespace App\UserBundle\Security; use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder as baseEncoder; class MessageDigestPasswordEncoder extends baseEncoder { private $algorithm; private $encodeHashAsBase64; private $iterations; public function __construct($algorithm = 'sha512', $encodeHashAsBase64 = true, $iterations = 5000) { $this->algorithm = $algorithm; $this->encodeHashAsBase64 = $encodeHashAsBase64; $this->iterations = $iterations; } public function encodePassword($raw, $salt) { if (!in_array($this->algorithm, hash_algos(), true)) { throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm)); } /* sfGuardUserは salt + raw password 他にの方法があると思いますがとりあえずはこれで */ if($this->algorithm == 'sha1'){ return sha1($salt.$raw); } $salted = $this->mergePasswordAndSalt($raw, $salt); $digest = hash($this->algorithm, $salted, true); for ($i = 1; $i < $this->iterations; $i++) { $digest = hash($this->algorithm, $digest.$salted, true); } return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest); } public function isPasswordValid($encoded, $raw, $salt) { return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt)); } }
5.app/config/parameters.ymlの編集
上記のMessageDigestPasswordEncoderクラスの場所をparameter.ymlに追加
security.encoder.digest.class: App\UserBundle\Security\MessageDigestPasswordEncoder
データ移行
ここまで来れば後はデータ移行でそれほど難しくはありません
http://qpleple.com/migrate-from-sfguard-to-fosuserbundle/
よりソースを拝借してきます。
$em = $this->getContainer()->get('doctrine.orm.entity_manager'); $um = $this->getContainer()->get('fos_user.user_manager'); $mysqli = new \mysqli($dbHost, $dbUser, $dbPassword, $dbName, $dbPort); $result = $mysqli->query('SELECT * FROM sf_guard_user'); $userSfGuard = $result->fetch_object(); while ($userSfGuard = $result->fetch_object()) { $userFOS = $um->createUser(); $userFOS->setUsername($userSfGuard->username); $userFOS->setEmail($userSfGuard->email_address); $userFOS->setPassword($userSfGuard->password); $userFOS->setSalt($userSfGuard->salt); $userFOS->setAlgorithm('sha1'); // sfGuardUserに合わせてください $em->persist($userFOS); } $em->flush();