配置Laravel Passport后,如何允许自有网站未登录用户访问API?
解决方案:限制API仅允许自有网站访问(无论用户是否登录)
嘿,这个需求我之前也碰到过,咱们可以通过自定义中间件来实现,替换掉原来的auth:api中间件逻辑,既允许未登录用户访问,又能挡住非自有网站的请求。
步骤1:创建自定义验证中间件
首先生成一个专门验证请求来源的中间件:
php artisan make:middleware VerifyOwnWebsite
步骤2:编写中间件验证逻辑
打开生成的app/Http/Middleware/VerifyOwnWebsite.php,替换成下面的代码,这里提供两种验证方式,你可以根据需求选一种(或者结合使用更安全):
方式一:通过Referer头验证域名
这种方式适合纯网页端的请求,检查请求的来源域名是否是你的自有网站:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class VerifyOwnWebsite { public function handle(Request $request, Closure $next): Response { // 这里替换成你的自有网站域名,多个的话用数组 $allowedDomains = ['your-domain.com', 'www.your-domain.com']; // 获取请求的Referer头 $referer = $request->headers->get('Referer'); if (!$referer) { return response()->json(['message' => 'Unauthorized access'], 403); } // 解析Referer提取域名 $parsedUrl = parse_url($referer); $domain = $parsedUrl['host'] ?? ''; // 验证域名是否在允许列表内 if (!in_array($domain, $allowedDomains)) { return response()->json(['message' => 'Unauthorized access'], 403); } // 验证通过,继续处理请求 return $next($request); } }
方式二:通过自定义请求头验证(更安全)
如果担心Referer头可能被篡改或缺失,可以用自定义密钥的方式,让前端请求时带上专属头:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class VerifyOwnWebsite { public function handle(Request $request, Closure $next): Response { // 从请求头获取自定义密钥,和.env里的配置对比 $requestSecret = $request->headers->get('X-OWN-WEBSITE-SECRET'); if ($requestSecret !== env('OWN_WEBSITE_SECRET')) { return response()->json(['message' => 'Unauthorized access'], 403); } return $next($request); } }
然后在你的.env文件里添加一个随机的密钥:
OWN_WEBSITE_SECRET=your-random-secret-string-here
同时要确保你的前端在所有API请求里都带上X-OWN-WEBSITE-SECRET这个请求头,值就是上面配置的密钥。
步骤3:注册中间件
打开app/Http/Kernel.php,在$routeMiddleware数组里添加我们的自定义中间件:
protected $routeMiddleware = [ // ... 其他中间件 'verify.own.website' => \App\Http\Middleware\VerifyOwnWebsite::class, ];
步骤4:更新路由配置
最后修改路由服务提供者里的mapApiRoutes方法,把原来的auth:api中间件换成我们的自定义中间件:
protected function mapApiRoutes() { Route::prefix('api') ->middleware('verify.own.website') ->namespace($this->namespace) ->group(base_path('routes/api.php')); }
补充说明
如果你的API需要区分登录用户和未登录用户的权限(比如登录用户能访问更多接口),可以同时保留auth:api中间件,但设置为可选:
// 路由里单独给需要登录的接口加auth:api // 比如在routes/api.php里 Route::get('/public-data', [YourController::class, 'publicData']); // 不需要登录,只要是自有网站就能访问 Route::get('/user-data', [YourController::class, 'userData'])->middleware('auth:api'); // 需要登录+自有网站
这样设置后,只有来自你自有网站的请求(不管用户是否登录)才能访问API,其他第三方客户端的请求会被直接拒绝~
内容的提问来源于stack exchange,提问作者panthro
相关产品推荐
相关产品推荐

