Как расширить или создать собственный метод PasswordBroker sendResetLink() в Laravel 5.8?

В настоящее время логика сброса пароля заключается в том, что пользователь должен указать действующий/зарегистрированный адрес электронной почты, чтобы получить сообщение электронной почты для восстановления пароля.

В моем случае я не хочу проверять, зарегистрирована ли электронная почта или нет из соображений безопасности, и я хочу просто выполнить внутреннюю проверку и сообщить пользователю, что «Если он предоставил зарегистрированную электронную почту, он должен получить электронное письмо для восстановления в ближайшее время».

То, что я сделал для этого, редактируется в методе 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, чтобы сохранить это изменение. всегда?

P.S. Я пробовал упомянутое здесь решение: Настройка брокера паролей Laravel 5.3, но это не помогло не работает .. также отличается дерево каталогов, и я не мог понять, куда поместить новый файл PasswordBroker.php.

Заранее спасибо!


person richardev    schedule 29.04.2019    source источник


Ответы (3)


Самым простым решением здесь было бы поместить ваш настраиваемый код в 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.");
}
person Dwight    schedule 30.04.2019
comment
Это как раз то, что я искал. Спасибо, @Dwight. - person richardev; 30.04.2019

Вот шаги, которые вам нужно выполнить.

Создайте новый пользовательский 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();
        });
    }
}

Как видите, этот провайдер расширяет базовый провайдер сброса пароля. Единственное, что изменилось, это то, что мы возвращаем пользовательский PasswordBrokerManager из метода registerPasswordBroker. Давайте создадим собственный менеджер брокера в том же пространстве имен:

<?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. Единственным отличием здесь является новый метод разрешения, который возвращает новый и пользовательский 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;
    }
}

Как видите, мы расширяем класс PasswordBroker по умолчанию из Laravel и переопределяем только тот метод, который нам нужно переопределить.

Последний шаг — просто заменить брокера Laravel Default PasswordReset нашим. В файле config/app.php измените строку, которая регистрирует провайдера как такового:

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

Это все, что вам нужно для регистрации пользовательского брокера паролей. Надеюсь, это поможет.

person Bahdcoder    schedule 30.04.2019
comment
Это похоже на решение выше, но оно работает. Это все еще слишком грязно, но это лучше, чем у меня. Спасибо. Я буду продолжать искать более упрощенное решение. - person richardev; 30.04.2019
comment
Спасибо! Вы написали четкое и краткое, но полностью закодированное описание того, как это сделать. У меня есть собственный брокер, который сбрасывает пароли для API. Отлично работает в Laravel 5.6. - person sifriday; 13.06.2019

Вы можете просто переопределить метод sendResetLinkFailedResponse в своем классе ForgetPasswordController.

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

Мы просто отправим успешный ответ, даже если проверка не удалась.

person mpskovvang    schedule 11.12.2020