Migrate from sfGuard to FOSUserBundle

Quentin Pleplé – 2011

That’s it, you took the big step: you decided to migrate your app from symfony 1 to Symfony 2. You just spent months to rewrite all your app from scratch and now you just have to import the data from your old version to have your Symfony 2 app up and running in production.

But the problem is: passwords are stored the same way by sfGuard and FOSUserBundle.

You will not be able to check with FOSUserBundle the password created with sfGuard for two reasons (if you kept default values):

I will show you how to change default in your new Symfony 2 application to deal with passwords the way sfGuard do.

Hashing Algorithm

Not very much work here, find the fos_user block in your config file and add the line telling FOSUserBundle that you want to use sha1 to hash passwords:

fos_user:
    # ...
    encoder:
        algorithm: sha1

Password and salt merging

We are going to overwrite the method used to merge passwords. Create a new folder Security/ in your bundle and add the file MessageDigestPasswordEncoder.php:

<?php
namespace Short\SiteBundle\Security;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder as BaseEncoder;
 
class MessageDigestPasswordEncoder extends BaseEncoder {
    // overwrite
    protected function mergePasswordAndSalt($password, $salt) {
        return $salt . $password;
    }
}

Don’t forget to change Short\SiteBundle according to your names.

Then add to your config file this line telling your app that we want to use that class instead of the default one:

parameters:
    security.encoder.digest.class: Short\SiteBundle\Security\MessageDigestPasswordEncoder

Don’t forget, here again, to change Short\SiteBundle according to your names.

That’s it

You may now write your script reading the sfGuard users and writing FOSUserBundle users. It will probably look like that:

$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->nickname);
    $userFOS->setEmail($userSfGuard->username);
    $userFOS->setPassword($userSfGuard->password);
    $userFOS->setSalt($userSfGuard->salt);
 
    $em->persist($userFOS);
}
$em->flush();

If so, you will have to add the method setSalt() to your User entity :

public function setSalt($salt) {
    $this->salt = $salt;
}

Having some problems?

If you are having trouble, try the parameters for the encoder in this post (it’s in French, but just look for the Symfony2 config file).

Feel free to ask questions right here ↓