#php #cakephp
#php #cakephp
Вопрос:
У меня есть следующая функция в приложении CakePHP 1.3, которая принимает токен и позволяет пользователю изменить свой пароль. Кажется, все работает нормально, за исключением того, что пароль на самом деле не меняется:/ Есть идеи, в чем проблема?
function admin_changepassword ( $token = null )
{
// If has a token or form has been submitted
if (!empty($token) || !(empty($this->data)))
{
$user = $this->User->find('first',array("MD5(User.email '".Configure::read('Security.salt')."')"=>$token));
if (empty($user))
{
$this->redirect(array('admin'=>false,'controller'=>'pages','action'=>'display','home'));
$this->Session->setFlash('Invalid token');
}
else
{
$this->set('user',$user);
if (!empty($this->data['User']['password']))
{
$user['User']['password'] = $this->data['User']['password'];
$this->User->save($this->data);
$this->Session->setFlash('Your password has been changed! Please log in.');
$this->redirect(array('admin'=>true,'controller' => 'users', 'action' => 'login'));
}
}
}
else
{
$this->redirect(array('admin'=>false,'controller'=>'home','action'=>'display','home'));
$this->Session->setFlash('No token');
}
}
Комментарии:
1. Вы просите свою базу данных хэшировать каждый пароль каждого пользователя для сравнения с этим запросом, что потенциально является чрезвычайно расточительной операцией.
2. Можете ли вы объяснить это подробнее, поскольку я не понимаю, и в этом причина того, что пароль не меняется?
3. Вы запрашиваете
WHERE MD5(password...) = 'somestring'
. Это означает, что база данных должна выполнятьсяMD5(password...)
для каждой строки, чтобы она могла сравнивать ее'somestring'
. Каким вообще должен быть этот токен? Я не думаю, что это ваша проблема. В чем именно ваша проблема? Что он делает?4. он не изменяет пароль в БД, даже если он показывает flash
5. Вы не устанавливаете
id
, что обновлять; если я не ошибаюсь. Я считаю, что cake создаст другую запись, если$Model->id
она не установлена.
Ответ №1:
Лично я бы сделал что-то подобное; но я предполагаю, что ваш пользователь действительно вошел в систему, используя auth
компонент или аналогичный. Непроверено; но логика выглядит так, как будто это должно сработать для меня.
<?php
function admin_changepassword ($token = NULL) {
// bail out early if there is no token set, and always set the flash before redirecting.
if($token==NULL) {
$this->Session->setFlash('No token');
$this->redirect(array('admin'=>false,'controller'=>'home','action'=>'display','home'));
}
// this is an admin action; the user already be logged in right?
$this->User->id = $this->Auth->user('id');
$user_password = $this->User->field('password');
// does the token match the hashed password, and did they enter a new password?
if($token==md5($user_password . Configure::read('Security.salt')) amp;amp; !empty($this->data['User']['password'])) {
$this->User->saveField('password', $this->data['User']['password']);
$this->Session->setFlash('Your password has been changed! Please log in.');
$this->redirect(array('admin'=>true,'controller' => 'users', 'action' => 'login'));
}
// somethings gone wrong/password was not updated
$this->Session->setFlash('Your password was not changed.');
$this->redirect(array('admin'=>false,'controller'=>'home','action'=>'display','home'));
}
Комментарии:
1. Нет, пользователь не войдет в систему, поскольку он меняет свой пароль, потому что он его забыл! Пользователь является администратором!
2. Но мой код определенно ЗНАЕТ, какой я пользователь, поскольку я показываю сообщение с приветственным адресом электронной почты в представлении, поэтому он знает, что он просто не меняет пароль :/
3. также
change password
отличается отforgot password
. Возможно, вы захотите взглянуть на переименование ваших методов, хотя бы по семантическим соображениям. Изменение подразумевает, что пользователь вошел в систему и хочет изменить свой пароль на что-то новое; следовательно, я предположил, что ваш пользователь вошел в систему.
Ответ №2:
Хорошо, после некоторого тестирования ваша проблема заключается в том, что я изначально предложил в своем комментарии.
Вы не устанавливаете id
своего пользователя, поэтому:
$this->User->save($this->data);
это не обновление пароля, это добавление новой строки в вашу базу данных.
Вам необходимо указать идентификатор пользователя для обновления.
$user = $this->User->find('first',array("MD5(User.email
'".Configure::read('Security.salt')."')"=>$token));
// this line is redundant
$user['User']['password'] = $this->data['User']['password'];
$this->User->id = $user['User']['id']; // set user id
$this->User->save($this->data); // save it
Если вы проверите свою users
таблицу, я подозреваю, что вы обнаружите, что есть много пустых записей с «измененным» паролем. Мое тестирование согласуется с руководством по cake.
Ответ №3:
Это старая тема, но она может кому-то помочь
function changePwd(){
$this->User->id = $this->data->['User']['id']; //assuming this is set
//check if the password fields are empty
//check if the password fields match (password and confirm password one)
//convert password
$this->request->data['User']['password'] = $this->Auth->password($this->data['User']['password'] );
//saveField worked for me
if($this->User->saveField('password',$this->request->data['User']['password'])){
$this->Session->setFlash('Password changed successfully.','flashSuccess');
}else{ ....
}