php 如何在 yii2 中添加散列密码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29490219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:26:30  来源:igfitidea点击:

how to add hashed passwords in yii2

phpyiihashloginyii2

提问by Matthew Smart

using Yii 2 basic Not the advanced version.

使用 Yii 2 basic 不是高级版本。

I have a crud admin authentication system. Which stores just an id, username and password in the database. When the user goes to log in if the username and password are correct they are logged in.

我有一个 crud 管理员身份验证系统。它只在数据库中存储一个 id、用户名和密码。当用户登录时,如果用户名和密码正确,则他们已登录。

However i now want to make these passwords secure so i want to salt and hash them. This is the part i am finding hard to do Or more so where to put things.

但是我现在想让这些密码安全,所以我想对它们进行加盐和散列。这是我发现很难做的部分,或者更多的是把东西放在哪里。

Part 1:I have an AdminController which goes along with my User Model Create.php page. Part 2:I have a siteController which goes along with the LoginForm model and the login.php page to log in.

第 1 部分:我有一个 AdminController,它与我的用户模型 Create.php 页面一起使用。 第 2 部分:我有一个 siteController,它与 LoginForm 模型和 login.php 页面一起用于登录。

I will go over part one first as it will obviously have to actually generate a hashed password here.

我将首先讨论第一部分,因为它显然必须在这里实际生成一个散列密码。

AdminController:

管理员控制器:

public function actionCreate()
{
    $model = new User();

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        return $this->redirect(['view', 'id' => $model->id]);
    } else {
        return $this->render('create', [
            'model' => $model,
        ]);
    }
}

User.php

用户名

    <?php

    namespace app\models;
    use yii\base\NotSupportedException;
    use yii\db\ActiveRecord;
    use yii\web\IdentityInterface;
    use yii\data\ActiveDataProvider;
    /**
     * User model
     *
     * @property integer $id
     * @property string $username
     * @property string $password
     */
class User extends ActiveRecord implements IdentityInterface
{


/**
 * @inheritdoc
 */
public static function tableName()
{
    return 'Users';
}


public function rules(){
        return [
            [['username','password'], 'required']
        ];
}



public static function findAdmins(){
    $query = self::find();

    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);

    return $dataProvider;

}


/**
 * @inheritdoc
 */
public static function findIdentity($id)
{
    return static::findOne(['id' => $id]);
}



/**
 * @inheritdoc
 */
public static function findIdentityByAccessToken($token, $type = null)
{
    throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}

/**
 * Finds user by username
 *
 * @param  string      $username
 * @return static|null
 */
public static function findByUsername($username)
{
    return static::findOne(['username' => $username]);
}

/**
 * @inheritdoc
 */
public function getId()
{
    return $this->id;
}

/**
 * @inheritdoc
 */
public function getAuthKey()
{
    return static::findOne('AuthKey');
}

/**
 * @inheritdoc
 */
public function validateAuthKey($authKey)
{
    return static::findOne(['AuthKey' => $authKey]);
}

/**
 * Validates password
 *
 * @param  string  $password password to validate
 * @return boolean if password provided is valid for current user
 */
public function validatePassword($password)
{
    return $this->password === $password;
}
}

Question??:So as you can see in this model i only have id, username and password coming from the database, so i take i will need to create one for field in db called "hashed_password"?

问题

create.php:

创建.php:

<?php $form = ActiveForm::begin(); ?>

<?= $form->field($model, 'username')->textInput(['maxlength' => 50]) ?>

<?= $form->field($model, 'password')->passwordInput(['maxlength' => 50]) ?>

<div class="form-group">
    <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end(); ?>

Right so that was part 1, the actual bit where the hashed password needs to be generated and saved into the database, how can i achieve this?

对,这是第 1 部分,需要生成散列密码并将其保存到数据库中的实际位,我该如何实现?

Okay moving on the Part2:

好的,继续第 2部分:

SiteController:

站点控制器:

public function actionLogin()
{
    if (!\Yii::$app->user->isGuest) {
        return $this->goHome();
    }

    $model = new LoginForm();

    if ($model->load(Yii::$app->request->post()) && $model->login()) {
        return $this->goBack();
    } else {
        return $this->render('login', [
            'model' => $model,
        ]);
    }
}

LoginForm.php (model):

LoginForm.php(模型):

class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;

private $_user = false;


/**
 * @return array the validation rules.
 */
public function rules()
{
    return [
        // username and password are both required
        [['username', 'password'], 'required'],
        // rememberMe must be a boolean value
        ['rememberMe', 'boolean'],
        // password is validated by validatePassword()
        ['password', 'validatePassword'],
    ];
}

/**
 * Validates the password.
 * This method serves as the inline validation for password.
 *
 * @param string $attribute the attribute currently being validated
 * @param array $params the additional name-value pairs given in the rule
 */
public function validatePassword($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUser();

        if (!$user || !$user->validatePassword($this->password)) {
            $this->addError($attribute, 'Incorrect username or password.');
        }
    }
}

/**
 * Logs in a user using the provided username and password.
 * @return boolean whether the user is logged in successfully
 */
public function login()
{
    if ($this->validate()) {
        return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
    } else {
        return false;
    }
}

/**
 * Finds user by [[username]]
 *
 * @return User|null
 */
public function getUser()
{
    if ($this->_user === false) {
        $this->_user = User::findByUsername($this->username);
    }

    return $this->_user;
}
}

Login.php:

登录.php:

<?php $form = ActiveForm::begin(); ?>

<?= $form->field($model, 'username'); ?> 
<?= $form->field($model, 'password')->passwordInput(); ?> 


<div class="form-group">
    <div class="col-lg-offset-1 col-lg-11">
        <?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
    </div>
</div>

So thats it, how do i integrate a hashed_password for each user when they create and then validate this upon login?

就是这样,我如何在每个用户创建时为每个用户集成一个 hashed_pa​​ssword,然后在登录时验证它?

I have been reading this on the documentation but just cant get this to work http://www.yiiframework.com/doc-2.0/guide-security-passwords.html

我一直在阅读文档中的内容,但无法使其正常工作http://www.yiiframework.com/doc-2.0/guide-security-passwords.html

回答by ineersa

When you creating user, you should generate and save password hash. To generate it

创建用户时,应生成并保存密码哈希。生成它

\Yii::$app->security->generatePasswordHash($password);

To check it on login, change your User model which implements UserIdentity

要在登录时检查它,请更改实现 UserIdentity 的 User 模型

    /**
     * Validates password
     *
     * @param  string $password password to validate
     * @return boolean if password provided is valid for current user
     */
    public function validatePassword($password)
    {
        return Yii::$app->getSecurity()->validatePassword($password, $this->password_hash);
    }

Instead of password_hash use your field from db.

使用 db 中的字段代替 password_hash。

回答by user776067

just reference Yii2 advance template user model implement.

只是参考 Yii2 高级模板用户模型实现。

/**
 * Generates password hash from password and sets it to the model
 *
 * @param string $password
 */
public function setPassword($password)
{
    $this->password_hash = Yii::$app->security->generatePasswordHash($password);
}

then overriding beforeSave method in User model to hash password before save to DB

然后覆盖用户模型中的 beforeSave 方法以在保存到数据库之前散列密码

public function beforeSave($insert)
{
    if(parent::beforeSave($insert)){
       $this->password_hash=$this->setPassword($this->password_hash);
       return true;
    }else{
       return false;
    }
}

Today we just apply PHP crypt function instead implementing password+salt hash algorithms youself,and it't more security than md5(password+salt)

今天我们只是应用PHP crypt函数,而不是自己实现password+salt hash算法,安全性不比md5(password+salt)

回答by Balaji Viswanath

You don't need a password_hash field in the database. You can use the "password" field to store the hashed password so that it is more secure and difficult to intruder to crack the password. Please modify the files as below,

您不需要数据库中的 password_hash 字段。您可以使用“密码”字段来存储经过哈希处理的密码,这样更安全且不易被入侵者破解。请修改文件如下,

User.php

用户名

<?php
namespace app\models;
use yii\base\NotSupportedException;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
use yii\data\ActiveDataProvider;

class User extends ActiveRecord implements IdentityInterface {


    //public $salt = "stev37f"; //Enter your salt here

    public static function tableName() {
        return 'Users';
    }

    public function rules() {
        return [
            [['username','password'], 'required']
        ];
    }

    public static function findAdmins() {
        $query = self::find();

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        return $dataProvider;

    }

    public static function findIdentity($id) {
        return static::findOne(['id' => $id]);
    }


    public static function findIdentityByAccessToken($token, $type = null) {
        throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
    }

    public static function findByUsername($username) {
        return static::findOne(['username' => $username]);
    }

    public function getId() {
        return $this->id;
    }

    public function getAuthKey() {
        return static::findOne('AuthKey');
    }

    public function validateAuthKey($authKey) {
        return static::findOne(['AuthKey' => $authKey]);
    }

    public function validatePassword($password) {
        return $this->password === static::hashPassword($password); //Check the hashed password with the password entered by user
    }

    public static function hashPassword($password) {// Function to create password hash
        $salt = "stev37f";
        return md5($password.$salt);
    }
}

Admin Controller

管理员控制器

public function actionCreate() {
    $model = new User();

    if ($model->load(Yii::$app->request->post()) && $model->validate()) {
        $model->password = User::hashPassword($model->password); // Hash the password before you save it.
        if($model->save())
            return $this->redirect(['view', 'id' => $model->id]);
    }
    return $this->render('create', [
       'model' => $model,
    ]);
}

To reset the password, you need to email a password reset link to the user.

要重置密码,您需要通过电子邮件将密码重置链接发送给用户。