通过电子邮件或手机在Laravel中重置密码



默认情况下,Laravel 5.5的密码重置系统适用于电子邮件,但我需要添加对手机号码的支持(通过OTP验证并生成令牌并重定向到密码重置页面(。我正在完成所有这部分,并在password_resets表上创建了一个移动列。

但问题是IlluminateAuthPasswordsDatabaseTokenRepository&IlluminateAuthPasswordsTokenRepositoryInterfaceONexist方法,并且它似乎是不可配置的。

public function exists(CanResetPasswordContract $user, $token)
{
$record = (array) $this->getTable()->where(
'email', $user->getEmailForPasswordReset()
)->first();
return $record &&
! $this->tokenExpired($record['created_at']) &&
$this->hasher->check($token, $record['token']);
}

我需要推翻那个方法。有这么多遗产在继承。我需要扩展哪些类,以及如何重写该方法。

如果您想覆盖IlluminateAuthPasswordsDatabaseTokenRepository方法的行为,您必须构建自己的令牌存储库,覆盖现有存储库中当前只检查数据库中"电子邮件"列的方法。确保您已经创建了一个迁移来添加适当的列:

<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
public function up(): void
{
$tname = config("auth.passwords.users.table");
Schema::table($tname, fn (Blueprint $t) => $t->string("mobile", 16));
}
public function down(): void
{
$tname = config("auth.passwords.users.table");
Schema::table($tname, fn (Blueprint $t) => $t->dropColumn("mobile"));
}
}

然后创建您的自定义存储库:

app/Auth/DatabaseTokenRepository.php

<?php
namespace AppAuth;
use IlluminateAuthPasswordsDatabaseTokenRepository as DatabaseTokenRepositoryBase;
use IlluminateContractsAuthCanResetPassword as CanResetPasswordContract;
use IlluminateSupportCarbon;
class DatabaseTokenRepository extends DatabaseTokenRepositoryBase;
{
//
// Override these methods to use mobile as well as email
//
public function create(CanResetPasswordContract $user)
{
$email = $user->getEmailForPasswordReset();
$mobile = $user->getMobileForPasswordReset();
$this->deleteExisting($user);
$token = $this->createNewToken();
$this->getTable()->insert($this->getPayload($email, $mobile, $token));
return $token;
}
protected function deleteExisting(CanResetPasswordContract $user)
{
return $this->getTable()
->where("email", $user->getEmailForPasswordReset())
->orWhere("mobile", $user->getMobileForPasswordReset())
->delete();
}
protected function getPayload($email, $mobile, $token): array
{
return [
"email" => $email,
"mobile" => $mobile,
"token" => $this->hasher->make($token),
"created_at" => new Carbon(),
];
}
public function exists(CanResetPasswordContract $user, $token)
{
$record = (array) $this->getTable()
->where("email", $user->getEmailForPasswordReset())
->orWhere("mobile", $user->getMobileForPasswordReset())
->first();
return $record &&
! $this->tokenExpired($record["created_at"]) &&
$this->hasher->check($token, $record["token"]);
}
public function recentlyCreatedToken(CanResetPasswordContract $user)
{
$record = (array) $this->getTable()
->where("email", $user->getEmailForPasswordReset())
->orWhere("mobile", $user->getMobileForPasswordReset())
->first();
return $record && $this->tokenRecentlyCreated($record['created_at']);
}
}

现在,您需要使用这个自定义令牌存储库,而不是默认的存储库。所以你必须覆盖另一个类。

app/Auth/PasswordBrokerManager.php

<?php
namespace AppAuth;
use IlluminateSupportStr;
use IlluminateAuthPasswordsPasswordBrokerManager as PasswordBrokerManagerBase;
class PasswordBrokerManager extends PasswordBrokerManagerBase
{
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 an instance of your new repository
// it's in the same namespace, no need to alias it
return new DatabaseTokenRepository(
$this->app['db']->connection($connection),
$this->app['hash'],
$config['table'],
$key,
$config['expire']
);
}
}

现在您已经创建了一个自定义代理来使用您的自定义存储库。你需要一个新的服务提供商来利用它

app/Providers/PasswordResetServiceProvider.php

<?php
namespace AppProviders;
use AppAuthPasswordBrokerManager;
use IlluminateAuthPasswordsPasswordResetServiceProvider as PasswordResetServiceProviderBase;
class PasswordResetServiceProvider extends PasswordResetServiceProviderBase
{
protected function registerPasswordBroker()
{
$this->app->singleton('auth.password', function ($app) {
// reference your new broker
// the rest of the method code is unchanged
return new PasswordBrokerManager($app);
});
$this->app->bind('auth.password.broker', function ($app) {
return $app->make('auth.password')->broker();
});
}
}

接下来,用应用程序配置中的自定义服务提供商替换默认密码重置服务提供商:app/config/app.php

<?php
return [
"providers" => [
...
// IlluminateAuthPasswordsPasswordResetServiceProvider::class,
AppProvidersPasswordResetServiceProvider::class,
...
],
];

最后,在您的用户模型上定义getMobileForPasswordReset()方法:

<?php
namespace App;
use IlluminateFoundationAuthUser as Authenticatable;
...
class User extends Authenticatable
{
...
public method getMobileForPasswordReset()
{
return $this->mobile;
}
}

最新更新