如何在cakephp3中请求使用电子邮件和纯文本密码登录

How to request for login with email and plain text password in cakephp3

我是 php 的新手,正在 cakephp3[=31= 中从事 REST API ] 我的 android 申请。

设置 phpcomposer 和路由后,我创建了 登录函数 ..

public function login() {
    $this->request->allowMethod('post');
    $this->loadModel('Users');
    $entity = $this->Users->newEntity($this->request->data, ['validate' => 'LoginApi']);
    if ($entity->errors()) {
        $this->httpStatusCode = 400;
        $this->apiResponse['message'] = 'Validation failed.';
        foreach ($entity->errors() as $field => $validationMessage) {
            $this->apiResponse['error'][$field] = $validationMessage[key($validationMessage)];
        }
    } else {
        $hasher = new DefaultPasswordHasher();
        $password = $hasher->hash($entity->password);

        $user = $this->Users->find()
            ->where([
                'email' => $entity->email,
                'password' => $password
            ])
            ->first();
        if (empty($user)) {
            $this->httpStatusCode = 403;
            $this->apiResponse['error'] = 'Invalid email or password.';
            return;
        }
        $payload = ['email' => $user->email, 'name' => $user->name];
        $this->apiResponse['token'] = JwtToken::generateToken($payload);
        $this->apiResponse['message'] = 'Logged in successfully.';
        isset($user);
        isset($payload);
    }
 }

我使用 123456 作为 密码 和这个 hasher returns 随机字符串每次,但是已经保存在数据库中的 123456 的密码是 $2y$10$f7K02jamD7ZeGHLcTkP6Weh6VsthMWHiwqHJmcqbsxuLCKGCQCGCu 这个。

这就是它给出无效密码作为响应的原因。

我的问题是如何为请求匹配完全相同的字符串或散列。 提前致谢。

一般的想法是根据您指定的密钥进行散列。

一个建议是定期更改密钥。然后,您将需要使用旧密钥再次将您的保存解密为明文,然后在新密钥上重新哈希。

我不确定您是否可以使用该选项,因此您可能希望对它持保留态度。

干杯

首先,CakePHP 附带了开箱即用的身份验证功能,我强烈建议您使用它而不是 运行 自己的,因为它听起来就好像您正在寻找确定性算法一样,这很容易适得其反。

如果您使用的是 CakePHP 3.5+,请查看 authentication middleware plugin (currently in RC phase), for earlier CakePHP versions, use the authentication component

为了完整起见,如果您要手动执行此操作,您将首先通过其唯一标识符(在您的示例中为电子邮件地址)查询用户,然后比较 PHP 处的密码级别,使用密码哈希器 AbstractPasswordHasher::check() 实现:

$user = $this->Users
    ->find()
    ->where([
        'email' => $this->request->data('email')
    ])
    ->first();

if (!$user ||
    $hasher->check($this->request->data('password'), $user->password) !== true
) {
    // authentication failed
} else {
    // authentication succeeded
}

参考这篇answer

使用这条线

password_verify($entity->password, $user->password)

而不是这个

$hasher = new DefaultPasswordHasher();
$password = $hasher->hash($entity->password);

你可以试试这个功能

public function login()
{
    $this->request->allowMethod('post');
    $this->loadModel('Users');
    $entity = $this->Users->newEntity($this->request->data, ['validate' => 'LoginApi']);
    if ($entity->errors()) {
        $this->httpStatusCode = 400;
        $this->apiResponse['message'] = 'Validation failed.';
        foreach ($entity->errors() as $field => $validationMessage) {
            $this->apiResponse['error'][$field] = $validationMessage[key($validationMessage)];
        }
    } else {
        $user = $this->Users->find()->where(['email' => $entity->email])->first();
        if (count($user)) {
            if (password_verify($entity->password, $user->password)) {
                $payload = ['email' => $user->email, 'password' => $user->password];
                $this->apiResponse['token'] = JwtToken::generateToken($payload);
                unset($user->password);
                $this->apiResponse['response'] = array($user);
                unset($user);
                unset($payload);
            } else {
                $this->httpStatusCode = 403;
                $this->apiResponse['error'] = 'Incorrect password';
                return;
            }
        } else {
            $this->httpStatusCode = 403;
            $this->apiResponse['error'] = 'Email not found';
            return;
        }
    }
}