Laravel 使用 Scramble 文档化 API 身份认证
本文中,我们将回顾 Laravel 中常见的 API 身份验证方法,以及如何使用 Scramble(Laravel 的现代 API 文档工具)文档化这些方法。
OpenAPI 规范支持多种 API 身份验证方法。通过最近的更新,Scramble 现在完全支持 OpenAPI 3.1.0 安全规范,允许你文档化规范中可用的任何身份验证方法。
Sanctum 身份验证
对于无状态身份验证,Sanctum 允许你在 Authorization
标头中发送身份验证令牌:
Authorization: Bearer ***
使用 Scramble,你可以使用以下代码文档化此身份验证。它应该添加到任何服务提供商的 boot
方法中:
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
public function boot()
{
Scramble::configure()
->withDocumentTransformers(function (OpenApi $openApi) {
$openApi->secure(
SecurityScheme::http('bearer')
);
});
}

这将为所有端点设置默认安全方案。
如果你使用 Sanctum 的有状态身份验证,并且 Scramble 的文档路由在正确的域上,你的身份验证会话将在“试用”中自动工作。
Passport 身份验证
对于 OAuth2 身份验证,OpenAPI 提供了 oauth2
安全方案。
Scramble 允许你精确指定 oauth2
的工作原理:
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Dedoc\Scramble\Support\Generator\SecuritySchemes\OAuthFlow;
public function boot()
{
Scramble::configure()
->withDocumentTransformers(function (OpenApi $openApi) {
$openApi->secure(
SecurityScheme::oauth2()
->flow('authorizationCode', function (OAuthFlow $flow) {
$flow
->authorizationUrl(config('app.url').'/oauth/authorize')
->tokenUrl(config('app.url').'/oauth/token')
->addScope('*', 'all');
})
);
});
}
你可以按此处所示定义所有 Scope,也可以为应用指定粒度 Scope。
Stoplight Elements UI(Scramble 的默认 UI)显示 oauth2
要求,而其他 UI(Scalar、Swagger)也允许用户直接从文档中获取 API 令牌。

文档化 Sanctum 的 oauth/token 端点
你可以使用 Scramble 文档化 Sanctum 的 oauth/token
端点。这是一个社区创建的扩展,可以帮助实现这一点:https://gist.github.com/tech-codivores/ddce2b10a64f06fe0b1bcd4868c17039
在使用扩展之前,请确保将其包含在 Scramble 的可文档化路由中:
Scramble::configure()
->routes(function (Route $r) {
return Str::startsWith($r->uri, 'api/'])
|| $r->uri === 'oauth/token';
})

自定义身份认证
多 header 身份认证
如果你的身份认证需要多个 header,你可以在 API 安全要求中指定它们:
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
public function boot()
{
Scramble::configure()
->withDocumentTransformers(function (OpenApi $openApi) {
$openApi->components->securitySchemes['tenant'] = SecurityScheme::apiKey('header', 'X-Tenant');
$openApi->components->securitySchemes['bearer'] = SecurityScheme::http('bearer');
$openApi->security[] = new SecurityRequirement([
'tenant' => [],
'bearer' => [],
]);
});
}
本例中,认证需要 X-Tenent
和 Authorzation
header。
查询参数中的 API token
如果你的 API token 作为查询参数传递,你可以使用这段代码将其文档化:
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
public function boot()
{
Scramble::configure()
->withDocumentTransformers(function (OpenApi $openApi) {
$openApi->secure(
SecurityScheme::apiKey('query', 'api_token');
);
});
}
你可以在 Scramble 文档中了解更多安全方案:https://scramble.dedoc.co/usage/authentication.
从身份认证要求中排除路由
使用 @unauthenticated
PHPDoc 注解,可以在身份认证中排除指定路由:
/**
* @unauthenticated
*/
public function index(Request $request)
{
return response()->json(/* some data */);
}
而 operation transformers 提供了更大的灵活性。
比如,要从没有 auth:
中间件的路由中删除身份验证要求:
public function boot()
{
Scramble::configure()
->withOperationTransformers(function (Operation $operation, RouteInfo $routeInfo) {
$routeMiddleware = $routeInfo->route->gatherMiddleware();
$hasAuthMiddleware = collect($routeMiddleware)->contains(
fn ($m) => Str::startsWith($m, 'auth:')
);
if (! $hasAuthMiddleware) {
$operation->security = [];
}
})
}
这会自动将没有身份验证中间件的路由标记为公共路由(public)。使用这种方法,你还可以为操作分配特定的安全要求。
小结
实现 API 身份验证的方法有很多,而 OpenAPI 涵盖了其中的大部分。
使用 Scramble,你可以文档化 API 的身份验证设置,甚至可以基于中间件自动化身份验证需求,从而避免手动注释。
如果你还没有尝试过 Scramble,试试吧! https://scramble.dedoc.co