为什么以及如何仅使用授权按钮生成空白的 swagger 页面?

问题描述 投票:0回答:1

在 API Platform 4 项目中,我需要为 swagger 文档提供身份验证安全性。

为此,我遵循了以下流程:API Platform secure swagger

如果我严格遵循代码,结果是:“访问此资源需要完全身份验证。(401)”

如果我进一步打开防火墙+控制访问,我可以查看我的所有文档资源,而无需从此 URL 进行任何授权控制:/api(这不是目标,因为不安全)

授权按钮和流程似乎已显示,但在禁止结果后生成请求,因为请求中没有 JWT 令牌。

如果使用以下方式访问 /api url,我也尝试不显示资源:

#[ApiResource(
    security: "is_granted('ROLE_ADMIN')",
)]

但它什么也没做,资源在没有授权控制的情况下再次显示

处理这段代码你能告诉我为什么以及如何生成一个空白的招摇页面,只有一个授权按钮才能在所有资源信息之后进行访问吗?

security.yaml

security:

  password_hashers:
    App\Entity\Users: 'auto'

  providers:
    users:
      entity:
        class: App\Entity\Users
        property: email

  firewalls:

    dev:
      pattern: ^/(_(profiler|wdt)|css|images|js)/
      security: false

    api:
      pattern: ^/api/
      stateless: true
      provider: users
      jwt: ~

    main:
      json_login:
        check_path: auth
        username_path: email
        password_path: password
        success_handler: lexik_jwt_authentication.handler.authentication_success
        failure_handler: lexik_jwt_authentication.handler.authentication_failure

  access_control:
    - { path: ^/$, roles: PUBLIC_ACCESS }
    - { path: ^/docs, roles: PUBLIC_ACCESS }
    - { path: ^/auth, roles: PUBLIC_ACCESS }
    - { path: ^/, roles: IS_AUTHENTICATED_FULLY }

api_platform.yaml

api_platform:
  swagger:
    api_keys:
      JWT:
        name: Authorization
        type: header

routes.yaml:

auth:
  path: /auth
  methods: ['POST']

controllers:
    resource:
        path: ../src/Controller/
        namespace: App\Controller
    type: attribute

最终目的是使用 JWT Token 进行安全的 swagger 显示。文档似乎缺少 API 平台 3 和 4 之间引擎的信息或更改。

symfony api-platform
1个回答
0
投票

您遇到的问题可能源于配置未完全集成 Swagger 和 API 平台的安全设置。以下是如何逐步解决这些问题,以实现需要通过 JWT 令牌进行身份验证的安全 Swagger UI:

为了确保 Swagger 本身是安全的,并且在显示资源之前只显示“授权”按钮,您需要调整 security.yaml 和 api_platform.yaml。

security.yaml 调整

security:
  password_hashers:
    App\Entity\Users: 'auto'

  providers:
    users:
      entity:
        class: App\Entity\Users
        property: email

  firewalls:
    dev:
      pattern: ^/(_(profiler|wdt)|css|images|js)/
      security: false

    api:
      pattern: ^/api/
      stateless: true
      provider: users
      jwt: ~

    main:
      json_login:
        check_path: auth
        username_path: email
        password_path: password
        success_handler: lexik_jwt_authentication.handler.authentication_success
        failure_handler: lexik_jwt_authentication.handler.authentication_failure

    docs:
      pattern: ^/docs
      stateless: true
      provider: users
      jwt: ~

  access_control:
    - { path: ^/$, roles: PUBLIC_ACCESS }
    - { path: ^/auth, roles: PUBLIC_ACCESS }
    - { path: ^/docs, roles: IS_AUTHENTICATED_FULLY }
    - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }

更新您的资源定义,以确保对未经授权的访问进行适当的控制。例如:

#[ApiResource(
    security: "is_granted('ROLE_ADMIN')",
    securityMessage: "Only admins can access this resource."
)]
class YourEntity
{
    // ...
}

这可确保资源隐藏在 Swagger UI 中,除非用户具有适当的角色。

更新您的 api_platform.yaml 文件以将 JWT 身份验证方案正确集成到 Swagger 中:

api_platform:
  swagger:
    api_keys:
      JWT:
        name: Authorization
        type: header
  defaults:
    pagination_client_items_per_page: true
  mapping:
    paths: ['%kernel.project_dir%/src/Entity']
  exception_to_status:
    Symfony\Component\Security\Core\Exception\AccessDeniedException: 403

在 src/OpenApi/OpenApiFactory.php 中,创建自定义 OpenAPI 定义以包含 JWT 授权按钮。

<?php

namespace App\OpenApi;

use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\OpenApi\OpenApi;
use ApiPlatform\OpenApi\Model\Components;
use ApiPlatform\OpenApi\Model\SecurityScheme;

final class OpenApiFactory implements OpenApiFactoryInterface
{
    private OpenApiFactoryInterface $decorated;

    public function __construct(OpenApiFactoryInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    public function __invoke(array $context = []): OpenApi
    {
        $openApi = $this->decorated->__invoke($context);

        $components = $openApi->getComponents() ?: new Components();
        $components = $components->withSecuritySchemes([
            'bearerAuth' => new SecurityScheme(
                type: 'http',
                scheme: 'bearer',
                bearerFormat: 'JWT',
            ),
        ]);

        $openApi = $openApi->withComponents($components);
        $openApi = $openApi->withSecurity([['bearerAuth' => []]]);

        return $openApi;
    }
}

在config/services.yaml中注册OpenAPI Factory服务:

services:
  App\OpenApi\OpenApiFactory:
    decorates: 'api_platform.openapi.factory'

所有操作后不要忘记清除缓存。

© www.soinside.com 2019 - 2024. All rights reserved.