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

Symfony5使用SelfValidatingPassport实现无用户ApiKey认证疑问

Symfony无用户体系下使用SelfValidatingPassport实现API Token校验方案

你当前代码直接进入onAuthenticationFailure的核心原因是:UserBadge默认会调用系统配置的用户提供器尝试加载用户,你没有配置适配token校验的用户加载逻辑,用户加载失败直接触发认证失败流程。

SelfValidatingPassport本身不需要额外的凭据校验步骤,只要其携带的所有Badge校验通过,即可完成认证。你不需要依赖数据库用户体系,只需要补充两个部分的实现:1. 极简的虚拟用户类 2. 自定义token校验逻辑的用户加载流程。


方案1:直接在UserBadge中传入自定义加载回调(最简方案)

该方案不需要额外创建UserProvider类,适合简单校验场景。

  1. 首先创建极简虚拟用户类,实现UserInterface接口:
// src/Security/DummyApiUser.php
namespace App\Security;

use Symfony\Component\Security\Core\User\UserInterface;

class DummyApiUser implements UserInterface
{
    public function __construct(private string $token) {}

    // 按需返回角色,比如API访问默认角色
    public function getRoles(): array
    {
        return ['ROLE_API'];
    }

    // 无密码场景返回空即可
    public function getPassword(): ?string
    {
        return null;
    }

    // 无盐场景返回空即可
    public function getSalt(): ?string
    {
        return null;
    }

    // 可以返回token作为用户标识
    public function getUserIdentifier(): string
    {
        return $this->token;
    }

    public function eraseCredentials() {}
}
  1. 修改你的authenticate方法,在UserBadge中传入自定义加载回调,直接编写token校验逻辑:
public function authenticate(Request $request): PassportInterface
{
    $apiToken = $request->headers->get('X-AUTH-TOKEN');

    if (null === $apiToken) {
        throw new CustomUserMessageAuthenticationException('No API token provided');
    }

    return new SelfValidatingPassport(
        new UserBadge($apiToken, function (string $token) {
            // 在这里写你的token校验逻辑,比如:
            // 1. 校验token是否在你预设的合法token列表中
            // 2. 校验token的签名是否有效、是否过期等
            $validTokens = ['your_valid_token_1', 'your_valid_token_2']; // 可替换为从配置/Redis中读取
            if (!in_array($token, $validTokens)) {
                throw new CustomUserMessageAuthenticationException('Invalid API token');
            }

            // 校验通过返回虚拟用户即可
            return new DummyApiUser($token);
        })
    );
}

方案2:自定义UserProvider实现(适合复用场景)

如果你有多处认证逻辑需要用到相同的token校验,可以创建自定义UserProvider统一维护校验规则:

  1. 创建UserProvider类:
// src/Security/ApiTokenUserProvider.php
namespace App\Security;

use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class ApiTokenUserProvider implements UserProviderInterface
{
    public function loadUserByIdentifier(string $identifier): UserInterface
    {
        // $identifier就是传入的token
        $validTokens = ['your_valid_token_1', 'your_valid_token_2'];
        if (!in_array($identifier, $validTokens)) {
            throw new UserNotFoundException();
        }

        return new DummyApiUser($identifier);
    }

    public function refreshUser(UserInterface $user): UserInterface
    {
        return $user;
    }

    public function supportsClass(string $class): bool
    {
        return DummyApiUser::class === $class;
    }
}
  1. 在config/packages/security.yaml中配置该用户提供器:
security:
    providers:
        api_token_provider:
            id: App\Security\ApiTokenUserProvider
    firewalls:
        api:
            pattern: ^/api
            provider: api_token_provider
            # 其余你的防火墙配置保持不变
  1. 你的原有authenticate方法不需要修改,UserBadge会自动调用该Provider完成token校验和用户加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 18:09:04