Страница 1 из 1

Авторизация с БД без ролей и прочего

Добавлено: 2014.11.25, 16:11
Dzhemal
Добрый день уважаемые форумчане.
Мучаюсь с авторизацией пользователей. Вместо demo/demo, admin/admin пытаюсь подключить к бд. Тема уже исхудавшая, читал предыдущие посты, а так же разные разделы документации (всё что касается авторизации), и всё равно кое-что не уловил.
Никакой ошибки у меня нет, но пользователь просто не залогинивается, пишет "Неправильный логин или пароль".

Код: Выделить всё

class LoginForm extends CFormModel
{
    public $username;
    public $password;
    public $rememberMe;
    private $_identity;

    public function rules()
    {
        return array(
            // username and password are required
            array('username, password', 'required'),
            // rememberMe needs to be a boolean
            array('rememberMe', 'boolean'),
            // password needs to be authenticated
            array('password', 'authenticate'),
        );
    }
    
    public function attributeLabels()
    {
        return array(
            'rememberMe'=>'Remember me next time',
        );
    }

    
    public function authenticate($attribute,$params)
    {
    if(!$this->hasErrors())
        {
            $this->_identity=new UserIdentity($this->username,$this->password);
            if(!$this->_identity->authenticate())
                $this->addError('password','Неправильный логин или пароль');
        }
    }

    
    public function login()
    {
        if($this->_identity===null)
        {
            $this->_identity=new UserIdentity($this->username,$this->password);
            $this->_identity->authenticate();
        }
        if($this->_identity->errorCode===UserIdentity::ERROR_NONE)
        {
            $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days
            Yii::app()->user->login($this->_identity,$duration);
            return true;
        }
        else
            return false;
    }
} 

Код: Выделить всё

class UserIdentity extends CUserIdentity
{
    private $_id;
    
    public function validatePassword($password)
    {
        return CPasswordHelper::verifyPassword($password,$this->password);
    }

    public function authenticate()
    {
        $username=strtolower($this->username);
        $user=monsters::model()->find('LOWER(username)=?',array($username));
        if($user===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        else if(!$user->validatePassword($this->password))
            $this->errorCode=self::ERROR_PASSWORD_INVALID;
        else
        {
            $this->_id=$user->id;
            $this->username=$user->username;
            $this->errorCode=self::ERROR_NONE;
        }
        return $this->errorCode==self::ERROR_NONE;
    }
 
    public function getId()
    {
        return $this->_id;
    } 
Модель регистрации:

Код: Выделить всё

class Monsters extends CActiveRecord
{
    public $verifyCode;
    
    public function tableName()
    {
        return 'monsters';
    }

    public function rules()
    {
        return array(
            array('username, password, email', 'required'),
            array('username, password, email', 'length', 'min'=>4, 'max'=>32),
            array('email', 'email', 'message'=>'Вы не корректно ввели e-mail адрес'),            // вывод своего сообщения об ошибке
            array('verifyCode', 'captcha', 'allowEmpty'=>!extension_loaded('gd')),
            // The following rule is used by search().
            // @todo Please remove those attributes that should not be searched.
            //array('id, login, password, email', 'safe', 'on'=>'search'),
        );
    }
    
    //...
    
    protected function beforeSave()  // Хэш пароля
    {
        if(parent::beforeSave())
        {
            if($this->isNewRecord)
            {
                $hash_pass = CPasswordHelper::hashPassword($this->password);
                $this->password = $hash_pass;
            }
            return true;
        }
        return false;
    }
    
    public function actionRegistration() {
    $q=new Monsters;
        if(isset($_POST['Monsters'])) {
        $q->attributes=$_POST['Monsters'];
            $q->username=$_POST['Monsters']['username'];
            $q->email=$_POST['Monsters']['email'];
            if($q->verifyCode=$_POST['Monsters']['verifyCode']){
            $q->save();
            }
        }
    }
} 
Подскажите пожалуйста, что я упустил? Уже много времени убил, но сам не смог додуматься.

Вобщем прошел дальше..Если в UserIdentity делать не так

Код: Выделить всё

public function authenticate()
    {
        $username=strtolower($this->username);
        $user=monsters::model()->find('LOWER(username)=?',array($username));
        if($user===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        

Код: Выделить всё

else if(!$user->validatePassword($this->password))
[/color]

Код: Выделить всё

            $this->errorCode=self::ERROR_PASSWORD_INVALID;
        else
        {
            $this->_id=$user->id;
            $this->username=$user->username;
            $this->errorCode=self::ERROR_NONE;
        }
        return $this->errorCode==self::ERROR_NONE;
    } 

а так

Код: Выделить всё

public function authenticate(){
        // Производим стандартную аутентификацию, описанную в руководстве.
        $user = monsters::model()->find('LOWER(username)=?', array(strtolower($this->username)));
        if(($user===null) || (($this->password)!==$user->password)) {
            $this->errorCode = self::ERROR_USERNAME_INVALID;
        } else {
            $this->_id = $user->id;
            $this->username = $user->username;
            $this->errorCode = self::ERROR_NONE;
        }
       return !$this->errorCode;
    } 
, то при вводе пароля который в бд не хеширован, авторизация проходит. Значит я что-то не правильно делаю с хешированием. Можно ли хешировать пароль в beforSave и правильно ли это? Как по человечески сделать валидацию на хешированный пароль путем CPasswordHelper::...??

Re: Авторизация с БД без ролей и прочего

Добавлено: 2014.11.26, 16:10
andrew68
В начале посмотрите какие ошибки пишет в /protected/runtime/application.log

Re: Авторизация с БД без ролей и прочего

Добавлено: 2014.11.26, 16:13
andrew68
а проверять хешированные пароли можно прямо в UserIdentity

Код: Выделить всё

if($user===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
else if($user->passwords!=md5($this->password))
            $this->errorCode=self::ERROR_PASSWORD_INVALID; 

Re: Авторизация с БД без ролей и прочего

Добавлено: 2014.11.26, 16:17
andrew68
Dzhemal писал(а): Можно ли хешировать пароль в beforSave и правильно ли это?

Код: Выделить всё

$q->attributes=$_POST['Monsters'];
$q->username=$_POST['Monsters']['username'];
$q->password=md5($_POST['Monsters']['password']);
$q->email=$_POST['Monsters']['email'];
if($q->verifyCode=$_POST['Monsters']['verifyCode']){
$q->save();
 

Re: Авторизация с БД без ролей и прочего

Добавлено: 2014.11.26, 16:47
Dzhemal
Если делать так, как вы написали, то ничего не хешируется.

Код: Выделить всё

$q->attributes=$_POST['Monsters'];
$q->username=$_POST['Monsters']['username'];
$q->password=md5($_POST['Monsters']['password']);
$q->email=$_POST['Monsters']['email'];
if($q->verifyCode=$_POST['Monsters']['verifyCode']){
$q->save();
Поэтому записал сам хэш в beforeSave. Делал уже проверку хэширования в UserIdentity, всё работает..с md5. А я всё хочу через CPasswordHelper::verifyPassword. Но никак не получается, я и так:

Код: Выделить всё

if(($user===null)||(!CPasswordHelper::verifyPassword($this->password,$user->password)))
            $this->errorCode=self::ERROR_PASSWORD_INVALID; 
, и другие порно-коды использовал, но вот эти ссылки мне подсказали что я так ничего не добьюсь.
http://www.yiiframework.ru/forum/viewtopic.php?t=13146
http://stackoverflow.com/questions/2039 ... fypassword
http://toster.ru/q/101353

Re: Авторизация с БД без ролей и прочего

Добавлено: 2014.11.26, 20:50
andrew68
Dzhemal писал(а):Если делать так, как вы написали, то ничего не хешируется.
для этого надо глянуть в лог приложения, чтобы посмотреть почему не хешируется. Нет смысла делать через beforeSave.

и кстати, раз уже есть строка

Код: Выделить всё

$q->attributes=$_POST['Monsters']; 
то дальнейшее присваивание не требуется, если поля в Monsters и $_POST['Monsters'] разные. Хотя в _POST есть verifyCode. Лучше сделать так.

Код: Выделить всё

$q=new Monsters;
if(isset($_POST['Monsters'])) {
    if(<что-то куда перед генераций формы сохраняется verifyCode - кука или сессия>==$_POST['Monsters']['verifyCode']){
        $q->setAttributes(array(
            'username'=>$_POST['Monsters']['username'],
            'password'=>CPasswordHelper::hashPassword($_POST['Monsters']['password']),
            'email'=>$_POST['Monsters']['email']
        ));
        if (!$q->save()){
            print_r($q->errors);
        }
    }
}
 

должно быть примерно так. А print_r($q->errors) нужен просто для просмотра ошибок, но это только на стадии отладки формы. С md5() должно работать тоже