API Platform 4如何生成仅含授权按钮的空白Swagger页面?
问题原因分析
- 严格配置时Swagger返回401:API Platform 4的Swagger UI依赖
/api/docs.json获取API Schema,该路径属于^/api/规则,被api防火墙强制要求JWT认证,导致Swagger加载失败。 - 放宽防火墙后资源暴露:若开放
/api/路径的公共访问,所有API资源的Schema和端点都会被未授权用户看到,违背安全需求。 security注解无法隐藏资源:该注解仅控制API端点的访问权限,不影响服务器端生成的Schema内容,未授权时Schema仍会包含所有资源定义。
解决方案
1. 调整安全配置,区分Swagger Schema与API资源的访问权限
修改security.yaml的access_control规则,允许/api/docs.json公开访问,同时保护其他/api/路径:
security: # 其他配置保持不变 access_control: - { path: ^/$, roles: PUBLIC_ACCESS } - { path: ^/docs, roles: PUBLIC_ACCESS } - { path: ^/auth, roles: PUBLIC_ACCESS } - { path: ^/api/docs.json, roles: PUBLIC_ACCESS } # 允许Schema公开访问 - { path: ^/api/, roles: IS_AUTHENTICATED_FULLY } # 保护其他API路径
2. 自定义Schema装饰器,未授权时过滤资源
创建一个Swagger装饰器,当用户未授权时,移除所有API资源的定义,只保留授权相关配置:
// src/OpenApi/JwtSecurityDecorator.php namespace App\OpenApi; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\OpenApi; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; final class JwtSecurityDecorator implements OpenApiFactoryInterface { public function __construct( private readonly OpenApiFactoryInterface $decorated, private readonly TokenStorageInterface $tokenStorage ) {} public function __invoke(array $context = []): OpenApi { $openApi = ($this->decorated)($context); $token = $this->tokenStorage->getToken(); // 未授权时,清空所有资源定义 if (!$token || !$token->getUser()) { $openApi->setPaths(new \ArrayObject()); $openApi->getComponents()->setSchemas(new \ArrayObject()); } return $openApi; } }
在services.yaml中注册该装饰器:
services: # 其他配置保持不变 App\OpenApi\JwtSecurityDecorator: decorates: 'api_platform.open_api.factory' arguments: ['@.inner', '@security.token_storage']
3. 验证效果
- 未授权访问
/docs:Swagger UI仅显示JWT授权按钮,无任何API资源。 - 输入有效JWT Token后:页面自动加载所有API资源,且能正常调用受保护的端点。
关键说明
API Platform 4相较于3.x,Schema生成逻辑与访问控制的绑定更严格,需通过装饰器主动过滤未授权时的资源定义,而非依赖端点的security注解。这样既保证Swagger UI可公开访问(仅显示授权按钮),又能保护API资源不被未授权用户查看和调用。
内容的提问来源于stack exchange,提问作者miltone
相关产品推荐
相关产品推荐

