Laravel 5:密码重置 - 将bcrypt密码移动到User.php模型?

时间:2016-02-02 15:03:26

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

我注意到有些开发人员修改了PasswordController.php,因此方法 resetPassword($ user,$ password)不会 bcrypt 密码。而是在模型 User.php 中输入密码 bcrypt

以下是一个示例:* 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 / ResetPasswords.php复制了resetPassword($ user,$ password)方法。它被修改,以便没有 bcrypt 密码。

以下是此方法最初的样子:

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

    $user->save();

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

(另外,正如您所见 - Auth :: guard($ this-&gt; getGuard()) - &gt; login($ user); 更改为 auth() - &GT;登录($用户);

我们的想法是在模型 Users.php 中创建一个mutator,其中密码将是 bcrypt ed。

所以,这是带有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() - &gt;登录($ user); Auth :: guard($ this-&gt ; getGuard()) - &gt;登录($ 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 个答案:

答案 0 :(得分: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。