【问题标题】:How to extend or make custom PasswordBroker sendResetLink() method in Laravel 5.8?如何在 Laravel 5.8 中扩展或制作自定义 PasswordBroker sendResetLink() 方法?
【发布时间】:2019-09-18 14:25:04
【问题描述】:

目前重置密码背后的逻辑是用户必须提供有效/注册的电子邮件才能接收密码恢复电子邮件。

就我而言,出于安全考虑,我不想验证电子邮件是否已注册,我只想在后端进行检查并告诉用户“如果他提供了已注册的电子-邮件,他应该很快就会收到恢复电子邮件”。

我为实现这一目标所做的工作是在 vendor\laravel\framework\src\Illuminate\Auth\Passwords\PasswordBroker.php sendResetLink() 方法中编辑的:

 /**
     * Send a password reset link to a user.
     *
     * @param  array  $credentials
     * @return string
     */
    public function sendResetLink(array $credentials)
    {
        // First we will check to see if we found a user at the given credentials and
        // if we did not we will redirect back to this current URI with a piece of
        // "flash" data in the session to indicate to the developers the errors.
        $user = $this->getUser($credentials);

        if (is_null($user)) {
            return static::INVALID_USER;
        }

        // Once we have the reset token, we are ready to send the message out to this
        // user with a link to reset their password. We will then redirect back to
        // the current URI having nothing set in the session to indicate errors.
        $user->sendPasswordResetNotification(
            $this->tokens->create($user)
        );

        return static::RESET_LINK_SENT;
    }

到这里:

 /**
     * Send a password reset link to a user.
     *
     * @param  array  $credentials
     * @return string
     */
    public function sendResetLink(array $credentials)
    {
        // First we will check to see if we found a user at the given credentials and
        // if we did not we will redirect back to this current URI with a piece of
        // "flash" data in the session to indicate to the developers the errors.
        $user = $this->getUser($credentials);

//        if (is_null($user)) {
//            return static::INVALID_USER;
//        }

        // Once we have the reset token, we are ready to send the message out to this
        // user with a link to reset their password. We will then redirect back to
        // the current URI having nothing set in the session to indicate errors.
        if(!is_null($user)) {
            $user->sendPasswordResetNotification(
                $this->tokens->create($user)
            );
        }

        return static::RESET_LINK_SENT;
    }

这个硬编码选项不是最好的解决方案,因为它会在更新后消失.. 所以 我想知道如何在 App 文件夹内的项目范围内扩展或实施此更改 始终保持这种变化?

附:我已经尝试过这里提到的解决方案:Laravel 5.3 Password Broker Customization 但它不起作用.. 目录树也不同,我不明白在哪里放置新的 PasswordBroker.php 文件。

提前致谢!

【问题讨论】:

    标签: php laravel laravel-5 laravel-5.8


    【解决方案1】:

    您可以在 ForgetPasswordController 类中重写 sendResetLinkFailedResponse 方法。

    protected function sendResetLinkFailedResponse(Request $request, $response)
    {
        return $this->sendResetLinkResponse($request, Password::RESET_LINK_SENT);
    }
    

    即使验证失败,我们也只会发送成功的响应。

    【讨论】:

      【解决方案2】:

      这里最简单的解决方案是将您的自定义代码放在 app\Http\Controllers\Auth\ForgotPasswordController 中 - 这是引入 SendsPasswordResetEmails 特征的控制器。

      您的方法会覆盖该特征提供的方法,因此将调用它而不是特征中的方法。您可以用您的代码覆盖整个 sendResetLinkEmail 方法,以始终返回相同的响应,无论成功与否。

      public function sendResetLinkEmail(Request $request)
      {
          $this->validateEmail($request);
      
          // We will send the password reset link to this user. Once we have attempted
          // to send the link, we will examine the response then see the message we
          // need to show to the user. Finally, we'll send out a proper response.
          $response = $this->broker()->sendResetLink(
              $request->only('email')
          );
      
          return back()->with('status', "If you've provided registered e-mail, you should get recovery e-mail shortly.");
      }
      

      【讨论】:

      • 这正是我正在寻找的。谢谢@Dwight
      【解决方案3】:

      以下是您需要遵循的步骤。

      创建一个新的自定义PasswordResetsServiceProvider。我有一个名为 Extensions 的文件夹(命名空间),我将在其中放置此文件:

      <?php
      
      namespace App\Extensions\Passwords;
      
      use Illuminate\Auth\Passwords\PasswordResetServiceProvider as BasePasswordResetServiceProvider;
      
      class PasswordResetServiceProvider extends BasePasswordResetServiceProvider
      {
          /**
           * Indicates if loading of the provider is deferred.
           *
           * @var bool
           */
          protected $defer = true;
      
          /**
           * Register the service provider.
           *
           * @return void
           */
          public function register()
          {
              $this->registerPasswordBroker();
          }
      
          /**
           * Register the password broker instance.
           *
           * @return void
           */
          protected function registerPasswordBroker()
          {
              $this->app->singleton('auth.password', function ($app) {
                  return new PasswordBrokerManager($app);
              });
      
              $this->app->bind('auth.password.broker', function ($app) {
                  return $app->make('auth.password')->broker();
              });
          }
      }
      

      如您所见,此提供程序扩展了基本密码重置提供程序。唯一改变的是我们从registerPasswordBroker 方法返回了一个自定义PasswordBrokerManager。让我们在同一个命名空间中创建一个自定义 Broker 管理器:

      <?php
      
      namespace App\Extensions\Passwords;
      
      use Illuminate\Auth\Passwords\PasswordBrokerManager as BasePasswordBrokerManager;
      
      class PasswordBrokerManager extends BasePasswordBrokerManager
      {
          /**
           * Resolve the given broker.
           *
           * @param  string  $name
           * @return \Illuminate\Contracts\Auth\PasswordBroker
           *
           * @throws \InvalidArgumentException
           */
          protected function resolve($name)
          {
              $config = $this->getConfig($name);
      
              if (is_null($config)) {
                  throw new InvalidArgumentException(
                      "Password resetter [{$name}] is not defined."
                  );
              }
      
              // The password broker uses a token repository to validate tokens and send user
              // password e-mails, as well as validating that password reset process as an
              // aggregate service of sorts providing a convenient interface for resets.
              return new PasswordBroker(
                  $this->createTokenRepository($config),
                  $this->app['auth']->createUserProvider($config['provider'] ?? null)
              );
          }
      }
      

      同样,这个 PasswordBrokerManager 从 laravel 扩展了基础管理器。这里唯一的区别是新的 resolve 方法,它从同一个命名空间返回一个新的和自定义的 PasswordBroker。所以最后一个文件我们将在同一个命名空间中创建一个自定义的PasswordBroker

      <?php
      
      namespace App\Extensions\Passwords;
      
      use Illuminate\Auth\Passwords\PasswordBroker as BasePasswordBroker;
      
      class PasswordBroker extends BasePasswordBroker
      {
       /**
           * Send a password reset link to a user.
           *
           * @param  array  $credentials
           * @return string
           */
          public function sendResetLink(array $credentials)
          {
              // First we will check to see if we found a user at the given credentials and
              // if we did not we will redirect back to this current URI with a piece of
              // "flash" data in the session to indicate to the developers the errors.
              $user = $this->getUser($credentials);
      
      //        if (is_null($user)) {
      //            return static::INVALID_USER;
      //        }
      
              // Once we have the reset token, we are ready to send the message out to this
              // user with a link to reset their password. We will then redirect back to
              // the current URI having nothing set in the session to indicate errors.
              if(!is_null($user)) {
                  $user->sendPasswordResetNotification(
                      $this->tokens->create($user)
                  );
              }
      
              return static::RESET_LINK_SENT;
          }
      }
      

      如您所见,我们从 Laravel 扩展了默认的 PasswordBroker 类,并且只覆盖了我们需要覆盖的方法。

      最后一步是简单地将 Laravel Default PasswordReset 代理替换为我们的代理。在config/app.php 文件中,更改注册提供程序的行:

      'providers' => [
      ...
      // Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
         App\Extensions\Passwords\PasswordResetServiceProvider::class,
      ...
      ]
      

      这就是注册自定义密码代理所需的全部内容。希望对您有所帮助。

      【讨论】:

      • 这就像上面的解决方案,但它确实有效。它仍然太乱了,但这比我的好。谢谢你。我会继续寻找更简单的解决方案。
      • 谢谢!你已经写了一个清晰简洁但完全编码的描述如何做到这一点。我有一个自定义代理可以针对 API 重置密码。在 Laravel 5.6 中运行良好。
      猜你喜欢
      • 2016-07-17
      • 1970-01-01
      • 2020-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-09
      相关资源
      最近更新 更多