【问题标题】:Laravel 5: Password Reset - move bcrypt password to User.php model?Laravel 5:密码重置 - 将 bcrypt 密码移动到 User.php 模型?
【发布时间】:2016-05-11 11:04:55
【问题描述】:

我注意到一些开发人员修改了 PasswordController.php,使得 resetPassword($user, $password) 方法不会 bcrypt 密码。相反,密码是在模型 User.phpbcrypt

这是一个例子:*app/Http/Controllers/Auth/*PasswordController.php

<?php

namespace SundaySlim\Http\Controllers\Auth;

use SundaySlim\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;

class PasswordController extends Controller
{

   use ResetsPasswords;

  public function __construct()
  {
      $this->redirectTo = route('backend.dashboard');
      $this->middleware('guest');
  }

  protected function resetPassword($user, $password)
  {
     $user->password = $password;
     $user->save();
     auth()->login($user);
  }
}

如您所见,从 vendor/laravel/framework/src/Illuminate/Foundation/Auth/ 复制了 resetPassword($user, $password) 方法 ResetPasswords.php强>。它已被修改,因此没有 bcrypting 密码。

这是这个方法最初的样子:

protected function resetPassword($user, $password)
{
    $user->password = bcrypt($password);

    $user->save();

    Auth::guard($this->getGuard())->login($user);
}

(同样,如您所见 - Auth::guard($this->getGuard())->login($user); 更改为 auth()->登录($user);)

这个想法是在模型 Users.php 中创建一个修改器,其中密码将被 bcrypted。

所以,这里是带有那个 mutator 的模型 User.php

<?php

namespace SundaySlim;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    public function setPasswordAttribute($value)
    {
        $this->attributes['password'] = bcrypt($value);
    }
}

问题:

1. 这样做的原因是什么(在 Users.php 中创建一个 mutator 到 bcrypt 密码而不是在 resetPassword($user, $password) 默认情况下)?为什么要将 bcrypting 密码从 resetPassword($user, $password) 移动到 User.php 模型,这样做有什么实际理由吗?

2. 有什么区别:auth()->login($user);Auth::guard($this->getGuard ())->login($user); ?

顺便说一下,这里是routes.php

Route::group(['middleware' => ['web']], function () {

    Route::get('backend/dashboard', [
        'uses'=>'Backend\DashboardController@index',
        'as'=>'backend.dashboard'
    ]);

    Route::controller('auth', 'Auth\AuthController', [
        'getLogin' => 'auth.login',
        'getLogout' => 'auth.logout'
    ]);

    Route::controller('auth/password', 'Auth\PasswordController', [
        'getEmail' => 'auth.password.email',
        'getReset' => 'auth.password.reset' 
    ]);
});

【问题讨论】:

  • 回答问题 1:有一个用于加密密码的突变体,防止开发人员绕过控制器方法并未能加密密码 - 他们不能只设置纯文本密码模型并保存。
  • 假设我是一名开发人员,编写以下代码:$user-&gt;password = 'something'; $user-&gt;save();。如果存在 mutator,则该密码将在保存之前在用户模型中加密。如果没有修改器,则该密码将作为纯文本保存在数据库中。
  • @Kryten 啊哈,我现在明白了。我想知道为什么 Laravel 默认在其 User.php 模型中没有这样的修改器,但我们需要修改 PasswordController.php (例如从 resetPassword($user, $password) 中删除 bcrypt 并在模型中创建修改器。 ..

标签: php laravel laravel-5 laravel-5.1 laravel-routing


【解决方案1】:

问题1的另一个答案:

你可以注册一个自定义的 UserProvider,这样你就可以覆盖 Laravel 安全实现的数据库部分。我今天花了一些时间对遗留数据库实施身份验证,其中密码存储为所提供密码的 md5 哈希值。这是通过注册一个自定义 UserProvider 来完成的,从身份验证的角度来看,它运行良好。

使用 bcrypt 然后设置密码是 Laravel 中的一个架构问题,因为这假设自定义 UserProvider 将存储密码的 bcrypt 哈希值。用 mutator 替换这个硬连线逻辑将逻辑放置在正确的位置 - 自定义 UserProviders 现在可以根据需要加载和存储身份验证数据。一般来说,即使是开箱即用的安全实施,也很难规定密码的加密方式。

上面提到的 PasswordController::resetPassword($user, $password) 覆盖的问题在于它涉及到内部逻辑的逆向工程——它浪费了时间去寻找和替换错误的行为,并且解决方法可能会停止工作在内部逻辑发生变化的任何时候。

仅供参考,还有另一种侵入性较小的黑客可以解决此问题。在设置新密码之前,会调用 UserProvider::retrieveByCredentials(array $credentials) 来验证并加载正在为其重置密码的用户。 $credentials 数组仅在密码重置时包含新的明文密码,因此您可以在密码重置流程中将密码缓存为属性。在 UserProvider::save() 上,忽略 bcrypt 哈希并改用缓存的密码。这确实意味着您必须拥有一个独立于实际用户模型的 AuthUser。

【讨论】:

    猜你喜欢
    • 2012-06-02
    • 2015-05-27
    • 2019-03-26
    • 2015-09-09
    • 2016-01-05
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多