You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel密码Broker中生成短有效期的4位数字重置令牌

实现Laravel自定义4位数字密码重置令牌

步骤1:创建自定义Password Broker类

在app/Providers/Auth目录下新建ApiUserPasswordBroker.php(目录不存在则手动创建),重写令牌生成与验证逻辑:

<?php

namespace App\Providers\Auth;

use Illuminate\Auth\Passwords\PasswordBroker as BasePasswordBroker;
use Illuminate\Support\Str;

class ApiUserPasswordBroker extends BasePasswordBroker
{
    /**
     * 生成4位数字重置令牌并保存
     *
     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
     * @return string
     */
    public function createToken($user)
    {
        $email = $user->getEmailForPasswordReset();
        
        // 清除用户已有的旧令牌
        $this->tokens->deleteExisting($user);
        
        // 生成唯一的4位数字令牌
        do {
            $token = Str::randomNumeric(4);
        } while ($this->tokens->exists($email, $token));
        
        // 存储令牌到数据库
        $this->tokens->create([
            'email' => $email,
            'token' => $token,
            'created_at' => now(),
        ]);
        
        return $token;
    }
    
    /**
     * 验证令牌有效性
     *
     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
     * @param  string  $token
     * @return bool
     */
    public function validateToken($user, $token)
    {
        $record = $this->tokens->get($user->getEmailForPasswordReset(), $token);
        
        return $record && !$this->tokenExpired($record);
    }
}

步骤2:替换默认的密码Broker

在app/Providers/AuthServiceProvider.php的boot方法中注册自定义Broker,替换api_users对应的默认实现:

<?php

namespace App\Providers;

use App\Providers\Auth\ApiUserPasswordBroker;
use Illuminate\Auth\Passwords\PasswordBrokerManager;
use Illuminate\Support\ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->registerPolicies();
        
        // 替换api_users的密码broker实例
        $this->app->extend(PasswordBrokerManager::class, function ($manager) {
            $manager->extend('api_users', function ($app) {
                $tokens = $app['auth.password.tokens'];
                $users = $app['auth']->createUserProvider('api_users');
                $view = $app['config']['auth.passwords.api_users.email'];
                
                return new ApiUserPasswordBroker(
                    $tokens, $users, $app['mailer'], $view
                );
            });
            
            return $manager;
        });
    }
}

步骤3:调整令牌表结构

默认password_reset_tokens表的token字段是为哈希值设计的长字段,现在修改为适合4位数字的长度:

  1. 若未创建表,修改迁移文件:
Schema::create('password_reset_tokens', function (Blueprint $table) {
    $table->string('email')->primary();
    $table->string('token', 4); // 限制长度为4
    $table->timestamp('created_at')->nullable();
});
  1. 若已存在表,创建新迁移修改字段:
Schema::table('password_reset_tokens', function (Blueprint $table) {
    $table->string('token', 4)->change();
});

步骤4:调整重置密码的验证逻辑

在重置密码的处理方法中,添加4位数字令牌的校验规则:

public function resetPassword(Request $request)
{
    $validator = Validator::make($request->all(), [
        'email' => 'required|email|exists:api_users,email',
        'token' => 'required|digits:4', // 强制验证4位数字
        'password' => 'required|confirmed|min:8',
    ]);

    if ($validator->fails()) {
        throw new ValidationException($validator);
    }

    $broker = Password::broker('api_users');
    $response = $broker->reset(
        $request->only('email', 'token', 'password', 'password_confirmation'),
        function ($user, $password) {
            $user->password = Hash::make($password);
            $user->save();
        }
    );

    return $response === Password::PASSWORD_RESET
        ? response()->json(['msg' => '密码重置成功'], 200)
        : response()->json(['msg' => '无效的令牌或邮箱'], 400);
}

注意事项

  • 4位数字令牌的安全性依赖于15分钟有效期和120秒限流配置,若需更高安全性可改为6位数字。
  • 生成令牌时必须校验唯一性,避免不同用户拿到重复令牌导致逻辑冲突。
  • 此处直接存储明文令牌,结合短有效期和限流规则,安全性可控,无需哈希存储。

内容的提问来源于stack exchange,提问作者Dimitrios Desyllas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 03:13:18