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

Vue应用对接Laravel Passport后端,如何避免服务器存储Client-ID?

解决Laravel Passport避免服务器存储Client-ID的自定义授权方案

核心思路是绕开Passport默认把Client ID、Scopes存会话的逻辑,改为加密传递客户端信息,在用户授权提交时再解密验证,完全不依赖会话存储。具体步骤如下:

1. 创建自定义授权控制器

新建app/Http/Controllers/OAuth/AuthorizationController.php,继承Passport的原控制器,重写关键方法:

<?php

namespace App\Http\Controllers\OAuth;

use Laravel\Passport\Http\Controllers\AuthorizationController as PassportAuthorizationController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;

class AuthorizationController extends PassportAuthorizationController
{
    // 重写显示授权页面的方法
    public function authorize(Request $request)
    {
        // 验证授权请求,拿到客户端和权限范围
        $authRequest = $this->server->validateAuthorizationRequest($request);
        $client = $authRequest->getClient();
        $scopes = $request->get('scope', []);

        // 不存会话,加密客户端信息为字符串
        $encryptedData = Crypt::encryptString(json_encode([
            'client_id' => $client->getIdentifier(),
            'scopes' => $scopes,
        ]));

        // 把加密数据传递到授权视图(可复用Passport默认视图或自定义Vue页面)
        return view('passport.authorize', [
            'client' => $client,
            'scopes' => $this->parseScopes($scopes),
            'encrypted_data' => $encryptedData,
            'request' => $request,
        ]);
    }

    // 重写用户同意授权的处理方法
    public function approve(Request $request)
    {
        // 解密请求中的客户端信息
        $decryptedData = json_decode(Crypt::decryptString($request->encrypted_data), true);
        
        // 验证客户端合法性,防止篡改
        $client = $this->server->getClientRepository()->getClientEntity($decryptedData['client_id']);
        if (!$client) {
            abort(403, '无效的客户端');
        }

        // 构造授权请求对象,替代原会话逻辑
        $authRequest = $this->server->validateAuthorizationRequest($request);
        $authRequest->setClient($client);
        $authRequest->setScopes($decryptedData['scopes']);

        // 调用Passport原生完成授权的逻辑
        return $this->server->completeAuthorizationRequest($authRequest, true);
    }

    // 重写用户拒绝授权的处理方法(逻辑同同意授权)
    public function deny(Request $request)
    {
        $decryptedData = json_decode(Crypt::decryptString($request->encrypted_data), true);
        $client = $this->server->getClientRepository()->getClientEntity($decryptedData['client_id']);
        
        if (!$client) {
            abort(403, '无效的客户端');
        }

        $authRequest = $this->server->validateAuthorizationRequest($request);
        $authRequest->setClient($client);
        $authRequest->setScopes($decryptedData['scopes']);

        return $this->server->completeAuthorizationRequest($authRequest, false);
    }
}

2. 修改授权视图的表单

如果用Passport默认视图,先执行php artisan vendor:publish --tag=passport-views发布视图文件,然后在resources/views/vendor/passport/authorize.blade.php的表单里添加隐藏字段:

<input type="hidden" name="encrypted_data" value="{{ $encrypted_data }}">

如果是Vue前端渲染授权页面,直接把encrypted_data作为参数传给组件,提交授权请求时一并携带即可。

3. 替换Passport默认路由

在app/Providers/AuthServiceProvider.php的boot方法里,替换默认授权路由指向自定义控制器:

use App\Http\Controllers\OAuth\AuthorizationController;
use Laravel\Passport\Passport;

public function boot()
{
    $this->registerPolicies();

    Passport::routes(function ($router) {
        // 移除默认的授权相关路由
        $router->forAuthorization()->except(['authorize', 'approve', 'deny']);
        // 注册自定义授权路由
        $router->get('/authorize', [AuthorizationController::class, 'authorize']);
        $router->post('/authorize', [AuthorizationController::class, 'approve']);
        $router->delete('/authorize', [AuthorizationController::class, 'deny']);
    });
}

关键注意事项

  • 加密安全性:必须用Laravel自带的Crypt类,它会自动为数据添加签名,防止恶意篡改Client ID等信息。
  • 无会话适配:如果你的应用完全不需要会话,可以在自定义控制器的构造方法中移除会话中间件,彻底脱离会话依赖。
  • SPA兼容:如果是纯Vue单页应用,授权页面可改为前端路由,后端只需返回加密后的encrypted_data和客户端基础信息,由Vue渲染授权界面后提交请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:50:25