Предоставленный ответ не помог мне переопределить правильный класс, но он дал мне некоторые идеи, как подойти к этому.В итоге я создал три класса, каждый из которых расширяет встроенные классы:
DatabaseTokenRepository
Здесь я сделал переопределения, чтобы разрешить свое пользовательское поведение;удаляйте только три самые старые записи при создании нового токена сброса и проверяйте несколько токенов при выполнении сброса.
<?php
namespace App\Services;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Auth\Passwords\DatabaseTokenRepository as DatabaseTokenRepositoryBase;
class DatabaseTokenRepository extends DatabaseTokenRepositoryBase
{
/**
* Create a new token record.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @return string
*/
public function create(CanResetPasswordContract $user)
{
$email = $user->getEmailForPasswordReset();
$this->deleteSomeExisting($user);
// We will create a new, random token for the user so that we can e-mail them
// a safe link to the password reset form. Then we will insert a record in
// the database so that we can verify the token within the actual reset.
$token = $this->createNewToken();
$this->getTable()->insert($this->getPayload($email, $token));
return $token;
}
/**
* Determine if a token record exists and is valid.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @param string $token
* @return bool
*/
public function exists(CanResetPasswordContract $user, $token)
{
$records = $this->getTable()
->where("email", $user->getEmailForPasswordReset())
->get();
foreach ($records as $record) {
if (
! $this->tokenExpired($record->created_at) &&
$this->hasher->check($token, $record->token)
) {
return true;
}
}
return false;
}
/**
* Delete SOME existing reset tokens from the database.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @return int
*/
protected function deleteSomeExisting($user)
{
// TODO: make this configurable in app config
$limit = 3;
$records = $this->getTable()
->where("email", $user->getEmailForPasswordReset())
->orderBy("created_at");
$ct = $records->count() - $limit + 1;
return ($ct > 0) ? $records->limit($ct)->delete() : 0;
}
}
PasswordBrokerManager
Это просто гарантирует, что мой пользовательскийкласс хранилища выше используется.Функция копируется точно из родительского класса, но, конечно, в другом пространстве имен.
<?php
namespace App\Services;
use Illuminate\Support\Str;
use Illuminate\Auth\Passwords\PasswordBrokerManager as PasswordBrokerManagerBase;
class PasswordBrokerManager extends PasswordBrokerManagerBase
{
/**
* Create a token repository instance based on the given configuration.
*
* @param array $config
* @return \Illuminate\Auth\Passwords\TokenRepositoryInterface
*/
protected function createTokenRepository(array $config)
{
$key = $this->app['config']['app.key'];
if (Str::startsWith($key, 'base64:')) {
$key = base64_decode(substr($key, 7));
}
$connection = $config['connection'] ?? null;
return new DatabaseTokenRepository(
$this->app['db']->connection($connection),
$this->app['hash'],
$config['table'],
$key,
$config['expire']
);
}
}
PasswordResetServiceProvider
Опять же, просто гарантируя, что пользовательскийкласс возвращается.Опять же, меняется только пространство имен.
<?php
namespace App\Providers;
use App\Services\PasswordBrokerManager;
use Illuminate\Auth\Passwords\PasswordResetServiceProvider as PasswordResetServiceProviderBase;
class PasswordResetServiceProvider extends PasswordResetServiceProviderBase
{
/**
* 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();
});
}
}
Наконец, конфигурация приложения обновляется:
// Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
App\Providers\PasswordResetServiceProvider::class,
И все прекрасно работает.