问题描述
我正在迁移使用 CakePHP 1.2 开发的 Web 应用程序 我正在将其迁移到版本 3.9.4。数据库中的用户密码都是使用 MD5 散列的,但 3.9.4 版本使用 bcrypt 作为默认散列器。我想使用 MD5,因此我可以使用 MD5 对用户进行身份验证。我已经完成了这个 article 并按照文章中的指导使用了 LegacyPasswordHasher 类,但它不起作用。这是我在 AppController 中配置 AuthComponent 的方法。
$this->loadComponent('Auth',[
'authenticate' => ['Form' => [
'passwordHasher' => [
'className' => 'Legacy',],'fields' => [
'username' => 'email','password' => 'password',]],'loginAction' => [
'controller' => 'Users','action' => 'login',]);
这是我的 LegcayPasswordHasher 类:
<?PHP
namespace App\Auth;
use Cake\Auth\AbstractPasswordHasher;
class LegacyPasswordHasher extends AbstractPasswordHasher {
public function hash($password) {
return md5($password);
}
public function check($password,$hashedPassword) {
$userPassword = md5($password);
return $userPassword === $hashedPassword;
}
}
这是旧系统中的 UserAuthComponent
。位于app/Controller/Component
。
class UserAuthComponent extends Component {
/**
* This component uses following components
*
* @var array
*/
var $components = array('Session','Cookie','RequestHandler','ControllerList');
/**
* configur key
*
* @var string
*/
var $configureKey='User';
function initialize(Controller $controller) {
}
function __construct(ComponentCollection $collection,$settings = array()) {
parent::__construct($collection,$settings);
}
function startup(Controller $controller = null) {
}
/**
* Called before the controller action. You can use this method to configure and customize components
* or perform logic that needs to happen before each controller action.
*
* @param object $c current controller object
* @return void
*/
function beforeFilter(&$c) {
Usermgm@R_404_6193@t($this);
$user = $this->__getActiveUser();
$pageRedirect = $c->Session->read('permission_error_redirect');
$c->Session->delete('permission_error_redirect');
$controller = $c->params['controller'];
$action = $c->params['action'];
$actionUrl = $controller.'/'.$action;
$requested= (isset($c->params['requested']) && $c->params['requested']==1) ? true : false;
$permissionFree=array('users/login','users/logout','users/register','users/userVerification','users/forgotPassword','users/activatePassword','pages/display','users/accessDenied','users/emailVerification','users/admin_login','schools/garminApi','schools/viewActivitymy','schools/viewbonuspointupdate','students/viewclassstudentleader','students/viewclassstudentleaderexport','schools/viewpointsupdate');
$access =str_replace(' ','',ucwords(str_replace('_',' ',$controller))).'/'.$action;
$allControllers=$this->ControllerList->getControllerWithMethods();
$errorPage=false;
if (!in_array($access,$allControllers)) {
$errorPage=true;
}
if( $action == "viewActivitymy" || $action == "viewActivitymycron" || $action == "viewActivitymycronfitbit"|| $action == "viewActivityfitbit" || $action=="viewPointactivity" || $action =="viewActivitymycron_manual" || $action =="viewbonuspointupdate" || $action =="viewpointsupdate" || $action =="viewclassstudentleader" || $action =="viewclassstudentleaderexport"){
}else{
if ((empty($pageRedirect) || $actionUrl!='users/login') && !$requested && !in_array($actionUrl,$permissionFree) && !$errorPage) {
App::import("Model","UserGroup");
$userGroupModel = new UserGroup;
if (!$this->isLogged()) {
if (!$userGroupModel->isGuestAccess($controller,$action)) {
$c->log('permission: actionUrl-'.$actionUrl,LOG_DEBUG);
$c->Session->write('permission_error_redirect','/users/login');
$c->Session->setFlash('You need to be signed in to view this page.');
$cUrl = '/'.$c->params->url;
if(!empty($_SERVER['QUERY_STRING'])) {
$rUrl = $_SERVER['REQUEST_URI'];
$pos =strpos($rUrl,$cUrl);
$cUrl=substr($rUrl,$pos,strlen($rUrl));
}
$c->Session->write('OriginAfterLogin',$cUrl);
$c->redirect('/login');
}
} else {
if (!$userGroupModel->isUserGroupAccess($controller,$action,$this->getGroupId())) {
$c->log('permission: actionUrl-'.$actionUrl,'/users/login');
$c->redirect('/accessDenied');
}
}
}
}
}
/**
* Used to check whether user is logged in or not
*
* @access public
* @return boolean
*/
public function isLogged() {
return ($this->getUserId() !== null);
}
/**
* Used to get user from session
*
* @access public
* @return array
*/
public function getUser() {
return $this->Session->read('UserAuth');
}
/**
* Used to get user id from session
*
* @access public
* @return integer
*/
public function getUserId() {
return $this->Session->read('UserAuth.User.id');
}
/**
* Used to get group id from session
*
* @access public
* @return integer
*/
public function getGroupId() {
return $this->Session->read('UserAuth.User.user_group_id');
}
/**
* Used to get group name from session
*
* @access public
* @return string
*/
public function getGroupName() {
return $this->Session->read('UserAuth.UserGroup.name');
}
/**
* Used to check is admin logged in
*
* @access public
* @return string
*/
public function isAdmin() {
$groupId = $this->Session->read('UserAuth.User.user_group_id');
if($groupId==ADMIN_GROUP_ID) {
return true;
}
return false;
}
/**
* Used to check is guest logged in
*
* @access public
* @return string
*/
public function isGuest() {
$groupId = $this->Session->read('UserAuth.User.user_group_id');
if(empty($groupId)) {
return true;
}
return false;
}
/**
* Used to make password in hash format
*
* @access public
* @param string $pass password of user
* @return hash
*/
public function makePassword($pass,$salt=null) {
return md5(md5($pass).md5($salt));
}
/**
* Used to make salt in hash format
*
* @access public
* @return hash
*/
public function makeSalt() {
$rand = mt_rand(0,32);
$salt = md5($rand . time());
return $salt;
}
/**
* Used to maintain login session of user
*
* @access public
* @param mixed $type possible values 'guest','cookie',user array
* @param string $credentials credentials of cookie,default null
* @return array
*/
public function login($type = 'guest',$credentials = null) {
$user=array();
if (is_string($type) && ($type=='guest' || $type=='cookie')) {
App::import("Model","User");
$usermodel = new User;
$user = $usermodel->authsomeLogin($type,$credentials);
} elseif (is_array($type)) {
$user =$type;
}
Configure::write($this->configureKey,$user);
$this->Session->write('UserAuth',$user);
return $user;
}
/**
* Used to delete user session and cookie
*
* @access public
* @return void
*/
public function logout() {
$this->Session->delete('UserAuth');
Configure::write($this->configureKey,array());
$this->Cookie->delete(LOGIN_COOKIE_NAME);
}
/**
* Used to persist cookie for remember me functionality
*
* @access public
* @param string $duration duration of cookie life time on user's machine
* @return boolean
*/
public function persist($duration = '2 weeks') {
App::import("Model","User");
$usermodel = new User;
$token = $usermodel->authsomePersist($this->getUserId(),$duration);
$token = $token.':'.$duration;
return $this->Cookie->write(
LOGIN_COOKIE_NAME,$token,true,// encrypt = true
$duration
);
}
/**
* Used to check user's session if user's session is not available then it tries to get login from cookie if it exist
*
* @access private
* @return array
*/
private function __getActiveUser() {
$user = Configure::read($this->configureKey);
if (!empty($user)) {
return $user;
}
$this->__useSession() || $this->__useCookietoken() || $this->__useGuestAccount();
$user = Configure::read($this->configureKey);
if (is_null($user)) {
throw new Exception(
'Unable to initilize user'
);
}
return $user;
}
/**
* Used to get user from session
*
* @access private
* @return boolean
*/
private function __useSession() {
$user = $this->getUser();
if (!$user) {
return false;
}
Configure::write($this->configureKey,$user);
return true;
}
/**
* Used to get login from cookie
*
* @access private
* @return boolean
*/
private function __useCookietoken() {
$token = $this->Cookie->read(LOGIN_COOKIE_NAME);
if (!$token) {
return false;
}
$user=false;
// Extract the duration appendix from the token
if(strpos($token,":") !==false) {
$tokenParts = split(':',$token);
$duration = array_pop($tokenParts);
$token = join(':',$tokenParts);
$user = $this->login('cookie',compact('token','duration'));
// Delete the cookie once its been used
}
$this->Cookie->delete(LOGIN_COOKIE_NAME);
if (!$user) {
return;
}
$this->persist($duration);
return (bool)$user;
}
/**
* Used to get login as guest
*
* @access private
* @return array
*/
private function __useGuestAccount() {
return $this->login('guest');
}
}
这是位于旧代码库中 User
处的 app/Mode/
模型。
App::uses('AppModel','Model');
App::uses('CakeEmail','Network/Email');
class User extends AppModel {
/**
* This model belongs to following models
*
* @var array
*/
var $belongsTo = array('UserGroup');
/**
* This model has following models
*
* @var array
*/
var $hasMany = array('LoginToken'=>array('className'=>'LoginToken','limit' =>1));
/**
* model validation array
*
* @var array
*/
var $validate = array();
/**
* UsetAuth component object
*
* @var object
*/
var $userAuth;
/**
* model validation array
*
* @var array
*/
function LoginValidate() {
$validate1 = array(
'email'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','message'=> 'Please enter email or username')
),'password'=>array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','message'=> 'Please enter password')
)
);
$this->validate=$validate1;
return $this->validates();
}
/**
* model validation array
*
* @var array
*/
function RegisterValidate() {
$validate1 = array(
//"user_group_id" => array(
//'rule' => array('comparison','!=',0),//'message'=> 'Please select group'),'school_name'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','message'=> 'Please enter school name','last'=>true),'mustUnique'=>array(
'rule' =>'isUnique','message' =>'This school name already taken',// 'mustBeLonger'=>array(
// 'rule' => array('minLength',4),// 'message'=> 'Username must be greater than 3 characters',// 'last'=>true),),'first_name'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','message'=> 'Please enter administrator first name')
),'last_name'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','on' => 'create','message'=> 'Please enter administrator last name')
),'email'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','message'=> 'Please enter email','mustBeEmail'=> array(
'rule' => array('email'),'message' => 'Please enter valid email','message' =>'This email is already registered',)
),'oldpassword'=>array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','message'=> 'Please enter old password','mustMatch'=>array(
'rule' => array('verifyOldPass'),'message' => 'Please enter correct old password'),'message'=> 'Please enter password','mustBeLonger'=>array(
'rule' => array('minLength',6),'message'=> 'Password must be greater than 5 characters','mustMatch'=>array(
'rule' => array('verifies'),'message' => 'Both passwords must match'),//'on' => 'create'
),'number_of_student'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','message'=> 'Please enter number of student')
),'tracker'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty','message'=> 'Please enter tracker number')
),'captcha'=>array(
'mustMatch'=>array(
'rule' => array('recaptchaValidate'),'message' => ''),)
);
$this->validate=$validate1;
return $this->validates();
}
/**
* Used to validate captcha
*
* @access public
* @return boolean
*/
public function recaptchaValidate() {
App::import("vendor","recaptcha/recaptchalib");
$recaptcha_challenge_field = (isset($_POST['recaptcha_challenge_field'])) ? $_POST['recaptcha_challenge_field'] : "";
$recaptcha_response_field = (isset($_POST['recaptcha_response_field'])) ? $_POST['recaptcha_response_field'] : "";
$resp = recaptcha_check_answer(PRIVATE_KEY_FROM_RECAPTCHA,$_SERVER['REMOTE_ADDR'],$recaptcha_challenge_field,$recaptcha_response_field);
$error = $resp->error;
if(!$resp->is_valid) {
$this->validationErrors['captcha'][0]=$error;
}
return true;
}
/**
* Used to match passwords
*
* @access public
* @return boolean
*/
public function verifies() {
return ($this->data['User']['password']===$this->data['User']['cpassword']);
}
/**
* Used to match old password
*
* @access public
* @return boolean
*/
public function verifyOldPass() {
$userId = $this->userAuth->getUserId();
$user = $this->findById($userId);
$oldpass=$this->userAuth->makePassword($this->data['User']['oldpassword'],$user['User']['salt']);
return ($user['User']['password']===$oldpass);
}
/**
* Used to send registration mail to user
*
* @access public
* @param array $user user detail array
* @return void
*/
public function sendRegistrationMail($user) {
// $user['User']['email'];
// send email to newly created user
$email = new CakeEmail();
$userId=$user['User']['id'];
$email->config('smtp');
$fromConfig = '[email protected]';
$fromNameConfig = 'Pradeep';
$email->from(array( $fromConfig => $fromNameConfig));
$email->sender(array( $fromConfig => $fromNameConfig));
$email->to($user['User']['email']);
$email->subject('Your registration is complete');
//$email->transport('Debug');
$body="Welcome ".$user['User']['first_name'].",Thank you for your registration on ".'http://localhost/garmin/register'." \n\n Thanks,\n".EMAIL_FROM_NAME;
try{
$result = $email->send($body);
} catch (Exception $ex) {
// we Could not send the email,ignore it
$result="Could not send registration email to userid-".$userId;
}
$this->log($result,LOG_DEBUG);
}
/**
* Used to send email verification mail to user
*
* @access public
* @param array $user user detail array
* @return void
*/
public function sendVerificationMail($user) {
$userId=$user['User']['id'];
$email = new CakeEmail();
$email->config('smtp');
$fromConfig = '[email protected]';
$fromNameConfig = 'Pradeep';
$email->from(array( $fromConfig => $fromNameConfig));
$email->sender(array( $fromConfig => $fromNameConfig));
$email->to($user['User']['email']);
$email->subject('Email Verification Mail');
$activate_key = $this->getActivationKey($user['User']['password']);
$link = Router::url("/userVerification?ident=$userId&activate=$activate_key",true);
$body="Hi,Click the link below to complete your registration \n\n ".$link;
try{
$result = $email->send($body);
} catch (Exception $ex){
// we Could not send the email,ignore it
$result="Could not send verification email to userid-".$userId;
}
$this->log($result,LOG_DEBUG);
}
/**
* Used to generate activation key
*
* @access public
* @param string $password user password
* @return hash
*/
public function getActivationKey($password) {
$salt = Configure::read ( "Security.salt" );
return md5(md5($password).$salt);
}
/**
* Used to send forgot password mail to user
*
* @access public
* @param array $user user detail
* @return void
*/
public function forgotPassword($user) {
$userId=$user['User']['id'];
$email = new CakeEmail();
$fromConfig = EMAIL_FROM_ADDRESS;
$fromNameConfig = EMAIL_FROM_NAME;
$email->from(array( $fromConfig => $fromNameConfig));
$email->sender(array( $fromConfig => $fromNameConfig));
$email->to($user['User']['email']);
$email->subject(EMAIL_FROM_NAME.': Request to Reset Your Password');
$activate_key = $this->getActivationKey($user['User']['password']);
$link = Router::url("/activatePassword?ident=$userId&activate=$activate_key",true);
$body= "Welcome ".$user['User']['first_name'].",let's help you get signed in
You have requested to have your password reset on ".EMAIL_FROM_NAME.". Please click the link below to reset your password Now :
".$link."
If above link does not work please copy and paste the URL link (above) into your browser address bar to get to the Page to reset password
Choose a password you can remember and please keep it secure.
Thanks,\n".
EMAIL_FROM_NAME;
try{
$result = $email->send($body);
} catch (Exception $ex){
// we Could not send the email,ignore it
$result="Could not send forgot password email to userid-".$userId;
}
$this->log($result,LOG_DEBUG);
}
/**
* Used to mark cookie used
*
* @access public
* @param string $type
* @param string $credentials
* @return array
*/
public function authsomeLogin($type,$credentials = array()) {
switch ($type) {
case 'guest':
// You can return any non-null value here,if you don't
// have a guest account,just return an empty array
return array();
case 'cookie':
$loginToken=false;
if(strpos($credentials['token'],":") !==false) {
list($token,$userId) = split(':',$credentials['token']);
$duration = $credentials['duration'];
$loginToken = $this->LoginToken->find('first',array(
'conditions' => array(
'user_id' => $userId,'token' => $token,'duration' => $duration,'used' => false,'expires <=' => date('Y-m-d H:i:s',strtotime($duration)),'contain' => false
));
}
if (!$loginToken) {
return false;
}
$loginToken['LoginToken']['used'] = true;
$this->LoginToken->save($loginToken);
$conditions = array(
'User.id' => $loginToken['LoginToken']['user_id']
);
break;
default:
return array();
}
return $this->find('first',compact('conditions'));
}
/**
* Used to generate cookie token
*
* @access public
* @param integer $userId user id
* @param string $duration cookie persist life time
* @return string
*/
public function authsomePersist($userId,$duration) {
$token = md5(uniqid(mt_rand(),true));
$this->LoginToken->create(array(
'user_id' => $userId,'expires' => date('Y-m-d H:i:s',));
$this->LoginToken->save();
return "${token}:${userId}";
}
/**
* Used to get name by user id
*
* @access public
* @param integer $userId user id
* @return string
*/
public function getNameById($userId) {
$res = $this->findById($userId);
$name=(!empty($res)) ? ($res['User']['first_name'].' '.$res['User']['last_name']) : '';
return $name;
}
/**
* Used to check users by group id
*
* @access public
* @param integer $groupId user id
* @return boolean
*/
public function isUserAssociatedWithGroup($groupId) {
$res = $this->find('count',array('conditions'=>array('User.user_group_id'=>$groupId)));
if(!empty($res)) {
return true;
}
return false;
}
}
这是旧代码库中位于 app/Controller
处的 UserController。
期待您的指导。提前致谢。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)