Search code examples
phpyiiyii2

How can I bcrypt a password during Yii2 Migrations?


I have a question. I have a migration file, that batchInserts an admin user and a normal user into a database. Now I have the files ready and they work fine. However, the password used to have a md5 hash during insert in Yii1.1 something like this: 'password'=>md5('admin')

My question is, can I do something similar in Yii2 with bcrypt? Where I encrypt the password during creation? I use batchInsert('users', ['column1', 'column2' ...], ['Jon', 'Doe' ...], ['Jane', 'Doe'...])

Any help is greatly appreciated!


Solution

  • The proper way to hash password in Yii2 is using yii\base\Security::generatePasswordHash(). This method uses password_hash() function with PASSWORD_DEFAULT constant as algorithm. I think currently that constant still refers to bcrypt algorithm. But it's meant to be future-proof. When PHP moves to another algorithm you wouldn't need to change your code. If the password_hash() function is not available the generatePasswordHash() methods fallback to crypt() function.

    In migration you can use application components in same way you would use them anywhere else. For example:

    $this->batchInsert(
        'users',
        ['first_name', 'last_name', 'password', ...],
        [
            ['John', 'Doe', Yii::$app->security->generatePasswordHash('mySecretPassword'), ...],
            ['Jane', 'Doe', Yii::$app->security->generatePasswordHash('anotherPassword'), ...],
        ]
    );
    

    Or if you prefer dependency injection approach:

    use yii\base\Security;
    use yii\db\Migration;
    
    class WhateverMigrationName extends Migration
    {
        private Security $security;
        public function __construct(Security $security, $config = [])
        {
            parent::__construct($config);
            $this->security = $security;
        }
    
        public function safeUp()
        {
            // ...
            $this->batchInsert(
                'users',
                ['first_name', 'last_name', 'password', ...],
                [
                    ['John', 'Doe', $this->security->generatePasswordHash('mySecretPassword'), ...],
                    ['Jane', 'Doe', $this->security->generatePasswordHash('anotherPassword'), ...],
                ]
            );
            // ...
        }
    
        // ...
    }
    

    To verify password against hash created by generatePasswordHash() you can call yii\base\Security::validatePassword() method in same way. For example:

    Yii::$app->security->validatePassword($password, $storedHash);