You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nelmio API Doc 3.4配置Swagger API-Key鉴权:校验逻辑位置咨询

配置API密钥存储与校验逻辑的实现步骤

首先得明确:Nelmio API Doc只是用来生成Swagger文档的工具,实际的密钥校验逻辑需要你在Symfony项目中自行实现,Nelmio的配置只负责展示文档层面的授权规则。下面一步步帮你搞定:

1. 安全存储你的API密钥

绝对不要把密钥硬编码到代码里,推荐用环境变量存储:

  • 在项目根目录的.env文件中添加(开发环境):
APP_API_KEY=abc123
  • 生产环境请通过服务器的环境变量配置(比如Nginx、Apache的环境变量设置,或者Docker的环境变量),避免密钥被提交到版本控制。

2. 实现API密钥的校验逻辑

这里提供两种常用的实现方式,按需选择:

方式一:用事件监听器(简单直接,适合小型项目)

创建一个请求监听器,在请求到达控制器前校验Header里的Authorization值:

// src/EventListener/ApiKeyListener.php
namespace App\EventListener;

use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class ApiKeyListener
{
    private $parameterBag;

    public function __construct(ParameterBagInterface $parameterBag)
    {
        $this->parameterBag = $parameterBag;
    }

    public function onKernelRequest(RequestEvent $event)
    {
        // 只校验API前缀的路由,避免影响非API请求
        $request = $event->getRequest();
        if (strpos($request->getPathInfo(), '/api') !== 0) {
            return;
        }

        $requestApiKey = $request->headers->get('Authorization');
        $validApiKey = $this->parameterBag->get('app_api_key');

        // 校验密钥是否存在且匹配
        if (!$requestApiKey || $requestApiKey !== $validApiKey) {
            $response = new Response('无效或缺失API密钥', Response::HTTP_UNAUTHORIZED);
            $event->setResponse($response);
        }
    }
}

然后在services.yaml中注册这个监听器:

# config/services.yaml
services:
    App\EventListener\ApiKeyListener:
        arguments:
            $parameterBag: '@parameter_bag'
        tags:
            - { name: kernel.event_listener, event: kernel.request }

方式二:用Symfony Security认证器(规范严谨,适合复杂权限场景)

如果你的项目用了Symfony Security组件,推荐用自定义认证器来处理:

// src/Security/ApiKeyAuthenticator.php
namespace App\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class ApiKeyAuthenticator extends AbstractAuthenticator
{
    private $parameterBag;

    public function __construct(ParameterBagInterface $parameterBag)
    {
        $this->parameterBag = $parameterBag;
    }

    public function supports(Request $request): ?bool
    {
        // 仅对API路由生效
        return strpos($request->getPathInfo(), '/api') === 0 && $request->headers->has('Authorization');
    }

    public function authenticate(Request $request): Passport
    {
        $requestApiKey = $request->headers->get('Authorization');
        $validApiKey = $this->parameterBag->get('app_api_key');

        if ($requestApiKey !== $validApiKey) {
            throw new AuthenticationException('无效的API密钥');
        }

        // 这里可以关联系统用户,不需要的话用匿名用户标识即可
        return new SelfValidatingPassport(new UserBadge('api-authenticated-user'));
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        // 认证成功,继续执行控制器逻辑
        return null;
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        $responseData = [
            'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
        ];

        return new Response(json_encode($responseData), Response::HTTP_UNAUTHORIZED, ['Content-Type' => 'application/json']);
    }
}

接着在security.yaml中配置防火墙:

# config/packages/security.yaml
security:
    enable_authenticator_manager: true
    firewalls:
        api:
            pattern: ^/api
            stateless: true
            custom_authenticators:
                - App\Security\ApiKeyAuthenticator

3. Swagger文档的优化(可选)

你已经完成了Swagger的授权规则配置,如果想让Swagger UI默认填充测试用的密钥(仅开发环境使用),可以在nelmio_api_doc.yaml中添加:

# config/packages/nelmio_api_doc.yaml
nelmio_api_doc:
    documentation:
        schemes: [https]
        securityDefinitions:
            app_api_key:
                type: apiKey
                description: 'App Api Key'
                name: Authorization
                in: header
        security:
            - app_api_key: []
    # 开发环境下让Swagger UI默认填充密钥,生产环境请删除这部分
    swagger:
        api_keys:
            app_api_key: 'abc123'

注意:这里的默认值只是方便测试,实际校验还是依赖你前面实现的逻辑,生产环境绝对不要配置这个,避免密钥泄露。


内容的提问来源于stack exchange,提问作者Zwen2012

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:35:02