symfony1.4 sfGuardUserからsymfony2 FOSUserBundleへの移行


symfony2が主流になって認証系はすべてFOSに絞られてきました。そこでそろそろsynfony1.4から移行するタイミングかなと思います。

方法に関して色々と調べてみると下記のソースにたどり着きます。

上記ソースで大体可能なのですが多少説明が足りない部分もあるので下記に方法をまとめておきます。

  • 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を作成します。

# vim 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();
  • このエントリーをはてなブックマークに追加

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です