如何为非基于用户的Laravel API实现授权?跨应用记账API权限保障
嘿,针对你的场景(两个独立Laravel应用调用Lumen记账API),我推荐以下几种成熟的授权方案,按实现复杂度从低到高排序,你可以根据自己的需求来选:
方案1:API密钥(API Key)认证
这是最直接、易实现的方案,非常适合服务间的简单授权场景。
实现步骤:
- 第一步:为餐厅和书店应用分别生成唯一的API密钥(可以用Laravel的
Str::random(60)生成),你可以把密钥存在Lumen的环境变量里,或者存入数据库的应用凭证表(如果需要动态管理多个客户端的话)。 - 第二步:在Lumen中创建自定义中间件验证API密钥:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class VerifyApiKey { public function handle(Request $request, Closure $next): Response { $apiKey = $request->header('X-API-Key'); // 这里可以根据实际情况验证:从环境变量取预设密钥,或者查数据库 $validKeys = [ env('RESTAURANT_APP_API_KEY'), env('BOOKSTORE_APP_API_KEY') ]; if (!in_array($apiKey, $validKeys)) { return response()->json(['message' => 'Unauthorized'], Response::HTTP_UNAUTHORIZED); } // 可选:把当前请求的应用标识存入请求上下文,方便后续业务逻辑使用 $request->attributes->set('app_type', $apiKey === env('RESTAURANT_APP_API_KEY') ? 'restaurant' : 'bookstore'); return $next($request); } }
- 第三步:在Lumen的
bootstrap/app.php中注册中间件:
$app->routeMiddleware([ 'api.key' => App\Http\Middleware\VerifyApiKey::class, ]);
- 第四步:给需要保护的API路由分组,应用这个中间件:
$router->group(['middleware' => 'api.key'], function () use ($router) { $router->post('/transactions', 'TransactionController@store'); });
- 第五步:在餐厅/书店的Laravel应用中,发起请求时携带API密钥:
// 餐厅应用发送交易请求示例 $response = Http::withHeaders([ 'X-API-Key' => env('LUMEN_API_KEY'), ])->post('https://your-lumen-api.com/transactions', [ 'amount' => 50.00, 'description' => '售出汉堡套餐', // 其他交易数据 ]);
方案2:HTTP Basic认证
如果不想自定义API密钥逻辑,HTTP Basic认证是另一种轻量的服务间授权选择。
实现步骤:
- 第一步:在Lumen中创建自定义Basic认证中间件(也可以用框架自带的,但自定义更灵活适配你的多客户端场景):
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class VerifyBasicAuth { public function handle(Request $request, Closure $next): Response { $username = $request->getUser(); $password = $request->getPassword(); // 验证餐厅或书店的凭证 $isRestaurantValid = ($username === env('RESTAURANT_APP_USER') && $password === env('RESTAURANT_APP_PASS')); $isBookstoreValid = ($username === env('BOOKSTORE_APP_USER') && $password === env('BOOKSTORE_APP_PASS')); if (!$isRestaurantValid && !$isBookstoreValid) { return response()->json(['message' => 'Unauthorized'], Response::HTTP_UNAUTHORIZED); } return $next($request); } }
- 第二步:在
bootstrap/app.php中注册中间件,然后给路由分组应用该中间件(和方案1的路由配置逻辑一致)。 - 第三步:Laravel应用中发起请求时携带Basic凭证:
$response = Http::withBasicAuth(env('LUMEN_API_USER'), env('LUMEN_API_PASS')) ->post('https://your-lumen-api.com/transactions', $transactionData);
方案3:Laravel Passport客户端凭证授权
因为你的两个应用都是Laravel生态,用Passport的客户端凭证授权是最契合的方案,安全性更高,还支持令牌过期、吊销等特性。
实现步骤:
- 第一步:在Lumen中安装并配置Passport(注意Lumen需要手动复制Passport的配置文件到项目中),然后为餐厅和书店各创建一个客户端凭证(通过
php artisan passport:client --client命令生成)。 - 第二步:在Lumen的
bootstrap/app.php中注册Passport的客户端中间件:
$app->routeMiddleware([ 'client' => Laravel\Passport\Http\Middleware\CheckClientCredentials::class, ]);
- 第三步:保护API路由:
$router->group(['middleware' => 'client'], function () use ($router) { $router->post('/transactions', 'TransactionController@store'); });
- 第四步:在餐厅/书店的Laravel应用中,先获取访问令牌再发起请求:
// 1. 获取客户端凭证令牌 $tokenResponse = Http::asForm()->post('https://your-lumen-api.com/oauth/token', [ 'grant_type' => 'client_credentials', 'client_id' => env('PASSPORT_CLIENT_ID'), 'client_secret' => env('PASSPORT_CLIENT_SECRET'), 'scope' => '', ]); $accessToken = $tokenResponse->json()['access_token']; // 2. 发送交易请求 $response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $accessToken, ])->post('https://your-lumen-api.com/transactions', $transactionData);
额外建议
- 无论用哪种方案,一定要确保API使用HTTPS,避免凭证在传输过程中被窃取。
- 可以在Lumen中添加日志记录,记录所有授权失败的请求,方便后续排查问题。
- 如果需要区分请求来自餐厅还是书店,可以在授权验证通过后,把应用标识存入请求上下文,后续业务逻辑就能直接使用。
内容的提问来源于stack exchange,提问作者Jk33
相关产品推荐
相关产品推荐

