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

Laravel Passport密码授权如何获取已有Bearer Token而非新建

Laravel Passport 复用有效密码授权令牌实现方案

Laravel Passport 原生密码授权逻辑每次请求都会生成全新令牌,且默认仅在oauth_access_tokens表存储令牌的哈希值(和密码存储逻辑一致,不可逆解密),因此要实现「返回已有有效令牌、不重复生成」的需求,不要直接修改原生oauth/token接口逻辑(避免后续升级Passport版本出现兼容问题),按以下步骤实现即可:

  • 第一步:新增独立路由
    建议使用POST方式传递账号密码(避免GET参数被浏览器历史、服务器日志留存导致密码泄露),如果要匹配给出的GET示例也可以直接按示例配置,在routes/api.php中添加路由:
use App\Http\Controllers\Auth\PassportTokenController;

// 生产环境推荐替换为Route::post
Route::get('oauth/token', [PassportTokenController::class, 'fetchValidToken']);
  • 第二步:调整数据库结构存储明文令牌
    因为原生Passport不存明文令牌,需要新增字段存储首次生成的明文内容,创建新的迁移文件:
// 迁移up方法内容
Schema::table('oauth_access_tokens', function (Blueprint $table) {
    $table->text('plain_access_token')->nullable()->comment('明文访问令牌,用于令牌复用');
});

执行php artisan migrate完成字段添加。

  • 第三步:编写控制器逻辑
    新建app/Http/Controllers/Auth/PassportTokenController.php,核心逻辑为「校验账号密码 -> 查询对应用户名下未撤销、未过期的有效令牌 -> 存在则直接返回,不存在则生成新令牌并存好明文后返回」:
<?php
namespace App\Http\Controllers\Auth;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Laravel\Passport\Token;
use App\Http\Controllers\Controller;

class PassportTokenController extends Controller
{
    public function fetchValidToken(Request $request)
    {
        // 参数校验,按实际的账号字段调整,示例中用name作为账号字段
        $validated = $request->validate([
            'name' => 'required|string',
            'password' => 'required|string',
        ]);

        // 查询用户并校验密码
        $user = User::where('name', $validated['name'])->first();
        if (!$user || !Hash::check($validated['password'], $user->password)) {
            return response()->json(['message' => '账号或密码错误'], 401);
        }

        // 查询用户名下有效令牌,可按需增加client_id、scope条件限定令牌范围
        $existingToken = Token::where('user_id', $user->id)
            ->where('revoked', 0)
            ->where('expires_at', '>', now())
            ->latest('expires_at')
            ->first();

        // 存在有效令牌直接返回
        if ($existingToken && $existingToken->plain_access_token) {
            return response()->json([
                'token' => $existingToken->plain_access_token
            ]);
        }

        // 无有效令牌则生成新令牌
        $newToken = $user->createToken('password_grant');
        $tokenModel = $newToken->token;
        // 令牌过期时间和原有Passport配置保持一致即可
        $tokenModel->expires_at = now()->addDays(15);
        // 存储明文令牌到新增字段
        $tokenModel->plain_access_token = $newToken->accessToken;
        $tokenModel->save();

        return response()->json([
            'token' => $newToken->accessToken
        ]);
    }
}

注意事项

  • 强烈不建议生产环境使用GET方式传递账号、密码参数,泄露风险远高于POST请求。
  • plain_access_token属于高度敏感字段,不要对非授权人员开放查询权限,有安全需求的话可以在存储时做应用层加密,读取时再解密。
  • 如果系统给不同端(APP/网页/小程序)分配了不同的Passport客户端,查询有效令牌时请加上client_id筛选条件,避免跨端返回错误令牌。
  • 令牌被用户主动撤销、过期后,下次请求会自动生成新令牌,不影响原有Passport的令牌生命周期逻辑。

内容的提问来源于stack exchange,提问作者Roman Dukhanin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:57:46