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
相关产品推荐
相关产品推荐

