我对 auth:api 中间件有疑问! 当我为未经身份验证的用户定义这样的路由时,我们有一个经过身份验证的用户和未经身份验证的用户都可以访问的请求:
Route::post('{user}/leads', 'UsersController@getContact');
当访客用户请求此路线时,一切正常。 是,我可以使用
$request->user();
访问用户
但是如果传递带有不记名标头的令牌并使用
$request->user()
获取用户,当然这是行不通的!因为我们在这条路线上没有使用auth:api
,如果我们这样做了,我们就无法与访客用户访问这条路线!
因此,我找不到一种为两个经过身份验证的用户定义一条路由的方法,如果用户经过身份验证,我们会得到 $request->user()
并且没有经过身份验证的用户也可以访问该路由!
提前致谢。
我找到了一种方法,我刚刚写了这个:
$middleware = ['api'];
if (\Request::header('Authorization'))
$middleware = array_merge(['auth:api']);
Route::group(['prefix' => 'v1', 'namespace' => 'Api', 'middleware' => $middleware], function () {
//routes here
});
在 api.php 路由文件中,它工作正常。 谢谢
这是因为
Auth
使用默认的 web
防护。您必须手动检查api
防护罩:
$user = Auth::user() ?? Auth::guard("api")->user();
那么你就不用使用任何
auth
中间件。如果用户是访客,则$user
将为null
,否则应设置。
我使用的解决方案是创建一个新的用于身份验证的中间件:
public function handle($request, Closure $next, ...$guards)
{
try
{
$this->authenticate($request, $guards);
}
catch(AuthenticationException $ex)
{
}
return $next($request);
}
在我路线的底部,我做了:
Route::middleware('auth_optional:api')->group(function () {
Route::get('services', [ServiceController::class,'index']);
});
这样,如果需要身份验证,它将分配正确的用户来请求,否则将以访客身份继续。我确实需要执行 $request->user() === null 来确保用户是访客
我想对经过身份验证的用户和未经身份验证的用户使用其他路由, 但关于这个主题,我添加了一种简单的方法:
在控制器的
__constructor
功能上添加这些行:
$authorizationHeader = \request()->header('Authorization');
if(isset($authorizationHeader)) {
$this->middleware('auth:api');
}
但我并不把这种方式集中作为最佳实践,这违反了单一责任原则。
如果你使用 Laravel Passport 那么这种方式会更干净。
在控制器中你可以直接获取用户
$user = $request->user('api');
这将为您提供经过身份验证的用户,如果不记名令牌无效,则不会抛出“未经身份验证”错误,但会导致空用户。
$middlewares = \Request::header('Authorization') ? ['jwt.verify', 'auth:api'] : [];
Route::middleware($middlewares)->group(function () {
Route::get('/get-product-details/{product_id}', 'App\Http\Controllers\Api\HomeSectionController@get_product_details');
});
基于@Roham Shojaei 的回答。看起来很可读。