Cake PHP 2.4.x. AuthComponent login()总是返回true [英] Cake PHP 2.4.x. AuthComponent login() always return true

查看:172
本文介绍了Cake PHP 2.4.x. AuthComponent login()总是返回true的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于非常长的问题,很抱歉,但我有auth-> login()的问题,经过长时间的调试,我想分享我的发现。



模型Cliente(相关部分):

 <?php 
App :: uses('AppModel','Model');
应用程序:: uses('BrValidation','Localized.Validation');
App :: uses('AuthComponent','Controller / Component');
App :: uses('SimplePasswordHasher','Controller / Component / Auth');

/ **
* Cliente模型
*
* /
类Cliente扩展AppModel {
public $ primaryKey ='idcliente';

public function beforeSave($ options = array()){
if(isset($ this-> data [$ this-> alias] ['password'
$ passwordHasher = new SimplePasswordHasher();
$ this-> data [$ this-> alias] ['password'] = $ passwordHasher-> hash(
$ this-> data [$ this-> alias] 'password']
);
}
return true;
}
}

ClientesController(相关部分):

 <?php 
App :: uses('AppController','Controller');
App :: uses('CakeEmail','Network / Email');

/ **
* Clientes控制器
*
* /
类ClientesController扩展AppController {

public $ components = array('Paginator','RequestHandler');

/ ** beforeFilter
*配置项执行命令
* /

public function beforeFilter(){
// parent :: beforeFilter();
// $ this-> Auth-> allow();
}
public function login(){

//如果已经登录,重定向
if($ this-> Session-> check Auth.Cliente')){
$ this-> redirect(array('action'=>'index'));
}

//如果我们得到发布信息,尝试验证
if($ this-> request-> is('post')){
CakeLog :: write('debug',POS IF POST\\\
);
if($ this-> Auth-> login()){
CakeLog :: write('debug',true no LOGIN\\\
);
$ this-> Session-> setFlash(__('Welcome,'。$ this-> Auth-> user('Cliente.username')));
$ this-> redirect($ this-> Auth-> redirectUrl());
} else {
$ this-> Session-> setFlash(__('Invalid username或password'));
}
}
}

AppController b $ b class AppController extends Controller {

  public $ components = array(
'DebugKit.Toolbar',
'Session',
'Auth'=> array(
'loginAction'=> array('controller'=>'clientes','action'=>'login') ,
'loginRedirect'=> array('controller'=>'clientes','action'=>'poslogin'),
'logoutRedirect'=& >'clientes','action'=>'login'),
'authError'=>'
'loginError'=> Usaárioou senhainválidos。Tente de novo。',
'authenticate'=> array(
'Form'=> array(
'userModel'=& b $ b'fields'=> array('username'=>'username','password'=>'password')



) );

无需发布关联视图,因为表单收集信息并按预期POST。 / p>

无论POSTed数据是什么,$ this-> Auth-> login()将始终返回TRUE。



蛋糕正在查找正确的表格和正确的用户,这是真的不重要的是用户是否存在和密码是否正确。我已经打开MySQL通用日志,以确保实际的查询是正确的,所以没有问题。



然后我移动到实际的Cake代码,并发现以下。我们感兴趣的代码位于 $ ROOT / lib / Cake / Controller / Component / AuthComponent.php ,第595-607行(login()函数)

  public function login($ user = null){
$ this-> _setDefaults

if(empty($ user)){
$ user = $ this-> identify($ this-> request,$ this-> response);
}
if($ user){
$ this-> Session-> renew();
$ this-> Session-> write(self :: $ sessionKey,$ user);
}
CakeLog :: write('debug',LOGGEDIN:。$ this-> loggedIn());
return $ this-> loggedIn();因为我们不传递任何参数,Cake会尝试
}


$ b <识别
用户(行599),然后将返回其 loggedIn 当前状态。 loggedIn 只是一个 user()调用的布尔结果,我们可以在第820-822行看到,请查看 user()(第648-658行)。

  public static function user($ key = null){
if(!empty(self :: $ _ user)){
$ user = self :: $ _ user;
} elseif(self :: $ sessionKey&&& CakeSession :: check(self :: $ sessionKey)){
$ user = CakeSession :: read(self :: $ sessionKey);
} else {
CakeLog :: write('debug',return null);
return null;
}
if($ key === null){
ob_start();
var_dump($ user);
$ d = ob_get_contents();
ob_clean();
CakeLog :: write('debug',return user:。。$ d);
return $ user;
}
CakeLog :: write('debug',return hash。Hash :: get($ user,$ key));
return Hash :: get($ user,$ key);
}

因为我们调用 user $ c>没有参数, $ key 将为NULL,代码将简单地 return $ user ,至少 - 这是问题所在。如果我 var_dump($ user)如上,我得到一个空数组,但我得到一些TRUE和登录过程suceeeds(当然是错误的) / p>

  2014-05-25 00:24:04 Debug:return user:array(1){
[Cliente ] =>
array(3){
[idcliente] =>
NULL
[username] =>
NULL
[password] =>
NULL
}
}



我使用Cake 2.4。 1,但我已经检查所有2.4版本到2.4.10和代码没有改变,所以这将发生在整个蛋糕2.4。我还没有查找其他小版本。我在OSX上运行PHP 5.5.3,但这对我来说听起来不太重要。



我没有读过任何ChangeLogs,对于这个问题,SO有一些未回答的问题。



我不想更改核心代码而不先共享,不知道如果SO是正确的地方



如果任何人可以散发一些光,运行一些想法,这将是非常感激。 p>

谢谢!

解决方案

我已经设法缩小问题



假设你有一个干净的浏览器会话,没有会议COOKIES。在这种情况下,代码将按预期工作。



但是,一旦登录,Cake将处理浏览器的会话cookie(CAKEPHP),除了其他信息,



如果您尝试再次登录(在当前登录之上), $ this-> ; Auth-> login()(无参数)将产生TRUE,无论什么。如果您提供了错误的用户/密码,它将坚持当前有效的。



除非您注销,否则会话Cookie过期(或者您手动将其删除,因为实例),无论是否使用参数调用 $ this-> Auth-> login()



从页面流/逻辑角度看,它似乎有意义(为什么会在登录后再次调用登录?),从用户行为的角度来看,这可能导致这里!)奇怪的问题。



让我们说你登录,做任何你想做的,离开你的网络应用程序,而不退出。您将在Cake的会话Cookie期间保持登录状态。如果您与其他人共享浏览器和应用程序,则此人可能会通过登录但输入密码错误地在您的帐户上工作,在这种情况下,如上所述, login()将返回TRUE,但WILL NOT CHANGE用户。



在任何情况下...强制使用 $ this-> Auth->



因为这种方法似乎在Cake 2.x中是存在的,所以我希望我的问题也澄清了其他人。


Sorry for the VERY long question, but I am having problems with auth->login() and after long hours of debugging, I would like to share my findings. It may well be something stupid on my side, but bear with me...

Model "Cliente" (relevant parts):

<?php
App::uses('AppModel', 'Model');
App::uses('BrValidation', 'Localized.Validation');
App::uses('AuthComponent', 'Controller/Component');
App::uses('SimplePasswordHasher', 'Controller/Component/Auth');

/**  
* Cliente Model
*
*/
class Cliente extends AppModel {
    public $primaryKey = 'idcliente';

public function beforeSave($options = array()) {
    if (isset($this->data[$this->alias]['password'])) {
        $passwordHasher = new SimplePasswordHasher();
        $this->data[$this->alias]['password'] = $passwordHasher->hash(
            $this->data[$this->alias]['password']
        );
    }
    return true;
}
}

ClientesController (relevant parts):

<?php
App::uses('AppController', 'Controller');
App::uses('CakeEmail', 'Network/Email');

/**
* Clientes Controller
*
*/
class ClientesController extends AppController {

public $components = array('Paginator','RequestHandler');

/** beforeFilter
*  Configura partes do sistema que podem ser acessadas sem login
*/ 

public function beforeFilter() {
    //parent::beforeFilter();
    //$this->Auth->allow();
}
public function login() {

    //if already logged-in, redirect
    if($this->Session->check('Auth.Cliente')){
        $this->redirect(array('action' => 'index'));      
    }

    // if we get the post information, try to authenticate
    if ($this->request->is('post')) {
        CakeLog::write('debug',"POS IF POST\n");
        if ($this->Auth->login()) {
            CakeLog::write('debug',"True no LOGIN\n");
            $this->Session->setFlash(__('Welcome, '. $this->Auth->user('Cliente.username')));
            $this->redirect($this->Auth->redirectUrl());
        } else {
            $this->Session->setFlash(__('Invalid username or password'));
        }
    } 
}

AppController (relevant parts) class AppController extends Controller {

public $components = array(
    'DebugKit.Toolbar',
    'Session',
    'Auth' => array(
        'loginAction' => array('controller' => 'clientes', 'action' => 'login'),
        'loginRedirect' => array('controller' => 'clientes', 'action' => 'poslogin'),
        'logoutRedirect' => array('controller' => 'clientes', 'action' => 'login'),
        'authError' => 'Você precisa se logar para ver esta página.',
        'loginError' => 'Usuário ou senha inválidos.  Tente de novo.',
        'authenticate' => array(
        'Form' => array(
            'userModel' => 'Cliente',
            'fields' => array ( 'username' => 'username', 'password' => 'password')
        )
    )

    ));

No need to post the associated view, as the Form collects the info and POSTs it as expected.

As it stands, $this->Auth->login() will ALWAYS return TRUE, regardless of the POSTed data. It really doesn't matter whether user exists or not and whether the password is correct or not.

Cake is looking up the right tables and right users. I have turned on MySQL General Log to ensure that the actual queries are correct, so no issues here.

I have then moved to the actual Cake code and found the following. The code we are interested is located at $ROOT/lib/Cake/Controller/Component/AuthComponent.php, lines 595-607 (the login() function), below:

public function login($user = null) {
    $this->_setDefaults();

    if (empty($user)) {
        $user = $this->identify($this->request, $this->response);
    }
    if ($user) {
        $this->Session->renew();
        $this->Session->write(self::$sessionKey, $user);
    }
    CakeLog::write('debug',"LOGGEDIN:". $this->loggedIn());
    return $this->loggedIn();
}

As we pass no arguments, Cake will attempt to identify the user (line 599) and then will return its loggedIn current status. loggedInis simply the boolean result for a user() call as we can see in lines 820-822, so let's have a look at user() (lines 648-658).

public static function user($key = null) {
    if (!empty(self::$_user)) {
        $user = self::$_user;
    } elseif (self::$sessionKey && CakeSession::check(self::$sessionKey)) {
        $user = CakeSession::read(self::$sessionKey);
    } else {
        CakeLog::write('debug',"return null");
        return null;
    }
    if ($key === null) {
        ob_start();
        var_dump($user);
        $d=ob_get_contents();
        ob_clean();
        CakeLog::write('debug',"return user: " . $d);
        return $user;
    }
    CakeLog::write('debug',"return hash" . Hash::get($user,$key));
    return Hash::get($user, $key);
}

Since we call user() with no arguments, $key will be NULL and the code will simply return $user and - to me, at least - that's where the problem lies. If I var_dump($user) as above, I get an empty array, but I get something "TRUE" and the login process "suceeeds" (erroneously of course).

2014-05-25 00:24:04 Debug: return user: array(1) {
  ["Cliente"]=>
  array(3) {
    ["idcliente"]=>
    NULL
    ["username"]=>
    NULL
    ["password"]=>
    NULL
 }
}

I am using Cake 2.4.1, but I have checked ALL 2.4 releases up to 2.4.10 and the code hasn't changed, so this will happen throughout Cake 2.4. I haven't looked up other minor versions though. I am running PHP 5.5.3 on OSX, but this doesn't sound too relevant to me here.

I haven't read any ChangeLogs where this issue is raised and there are some unanswered questions in SO regarding this issue.

I didn't want to change core code without sharing first and am not sure if SO is the "proper" place to post this, and it could well be that I am simply overlooking something.

If anybody can shed some light and run some thoughts, that would be really appreciated.

Thanks!

解决方案

I have managed to narrow down the issue and while it doesn't seem to a bug in the core code, it does seem to qualify as a behaviour to be investigated further.

Assume you have a "clean" browser session, with NO SESSION COOKIES. In this case, the code will work as expected. Wrong users and/or passwords will be denied.

However, once you log on, Cake will handle the browser a session cookie (CAKEPHP) which, among other info, will link that session to the logged user.

If you try to log again ("on top of your current login"), $this->Auth->login() (without parameters) will yield TRUE no matter what. If you provide a wrong user/password, it will stick to the current valid one. If you provide a valid user/password, it will CHANGE to the new user.

Unless you log out, or the session cookie expires (or you manually delete it, for instance), it doesn't matter whether you call $this->Auth->login() with or without parameters.

While from a "page flow"/logical perspective it seems to makes sense (why would one call "Login" AGAIN after being logged in?), from a user behaviour perspective, this can lead to (as noticed here!) weird problems.

Let's say you log in, do whatever you want to do and leave your web app without logging out. You will remain logged in for the duration of Cake's Session Cookie. If you share the browser and the app with someone else, this someone may accidentally work on your account, by logging in but mistyping the password, in which case, as mentioned above, login() will return TRUE, but WON'T CHANGE users. Not to mention, potentially malicious uses.

In any case... it's probably good practice to force a $this->Auth->logout() before logging in to avoid potential app misbehaviours.

Since this approach seems to be present throughout Cake 2.x, I hope my issues clarifies other people as well.

这篇关于Cake PHP 2.4.x. AuthComponent login()总是返回true的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆