Cake PHP 2.4.x. AuthComponent login()始终返回true

Pba*_*bal 3 cakephp cakephp-2.0

对于非常长的问题很抱歉,但我遇到了auth-> login()的问题,经过长时间的调试后,我想分享我的发现.这可能是我身边的蠢事,但请耐心等待......

型号"Cliente"(相关部分):

<?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;
}
}
Run Code Online (Sandbox Code Playgroud)

ClientesController(相关部分):

<?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'));
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

AppController(相关部分)类AppController扩展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')
        )
    )

    ));
Run Code Online (Sandbox Code Playgroud)

无需发布关联的视图,因为表单收集信息并按预期POST.

不管发布的数据如何,$ this-> Auth-> login()将始终返回TRUE.用户是否存在以及密码是否正确无关紧要.

Cake正在查找正确的表和正确的用户.我打开了MySQL General Log以确保实际查询是正确的,所以这里没有问题.

然后我转移到实际的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();
}
Run Code Online (Sandbox Code Playgroud)

由于我们没有传递任何参数,Cake将尝试向identify用户(第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);
}
Run Code Online (Sandbox Code Playgroud)

因为我们调用user()没有参数,所以$key将是NULL并且代码将简单地return $user- 至少对我来说 - 这就是问题所在.如果我var_dump($user)如上所述,我得到一个空数组,但我得到一些"TRUE"并且登录过程"suceeeds"(当然是错误的).

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

我正在使用Cake 2.4.1,但是我检查了所有2.4版本高达2.4.10并且代码没有改变,所以这将在Cake 2.4中发生.我没有查找其他次要版本.我在OSX上运行PHP 5.5.3,但这对我来说听起来并不太重要.

我没有阅读任何提出此问题的ChangeLogs,并且在此问题上有一些未解决的问题.

我不想在没有共享的情况下更改核心代码,并且不确定SO是否是发布此内容的"正确"位置,而且很可能是我只是忽略了某些内容.

如果任何人都可以放下一些亮点并运行一些想法,那将非常感激.

谢谢!

Pba*_*bal 6

我已经设法缩小了问题的范围,虽然它似乎没有核心代码中的错误,但似乎确实有资格作为进一步调查的行为.

假设你有一个"干净"的浏览器会话,没有SESSION COOKIES.在这种情况下,代码将按预期工作.错误的用户和/或密码将被拒绝.

但是,一旦您登录,Cake将在浏览器中处理会话cookie(CAKEPHP),其中包括将该会话链接到已登录用户的信息.

如果您尝试再次登录("在当前登录之上"),$this->Auth->login()(无参数)无论如何都将产生TRUE.如果您提供了错误的用户/密码,它将坚持当前有效的用户/密码.如果您提供有效的用户/密码,它将更改为新用户.

除非您注销,或者会话cookie过期(或者您手动删除它),否则无论是否$this->Auth->login()使用参数调用都无关紧要.

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

假设你登录,做你想做的任何事情并离开你的网络应用程序而不退出.您将在Cake的会话Cookie期间保持登录状态.如果您与其他人共享浏览器和应用程序,此人可能会意外地使用您的帐户,通过登录但输入密码错误,在这种情况下,如上所述,login()将返回TRUE,但不会更改用户.更不用说,潜在的恶意用途.

在任何情况下...... $this->Auth->logout()在登录之前强制执行以避免潜在的应用程序错误行为可能是一种好习惯.

由于这种方法似乎贯穿Cake 2.x,我希望我的问题也能澄清其他人.