Symfony 5 ApiKeyAuthenticator 与 SelfValidatingPassport

con*_*ind 12 php authentication api-key symfony symfony5

我正在开发一个新的 Symfony 5.3.6 项目,并希望基于新系统实施身份验证,如下所示:

\n
\n

https://symfony.com/doc/current/security/authenticator_manager.html#creating-a-custom-authenticator

\n
\n

我没有任何用户,只想检查发送的 api 令牌是否正确,因此在实现此方法时:

\n
public function authenticate(Request $request): PassportInterface\n{\n    $apiToken = $request->headers->get(\'X-AUTH-TOKEN\');\n\n    if (null === $apiToken) {\n        // The token header was empty, authentication fails with HTTP Status Code 401 "Unauthorized"\n        throw new CustomUserMessageAuthenticationException(\'No API token provided\');\n    }\n\n    return new SelfValidatingPassport(new UserBadge($apiToken));\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

具体在哪里进行检查?我是否忘记在某个地方实现另一个类?

\n

如果我保留代码,它会直接进入onAuthenticationFailure.

\n

据我所知,我可以使用属性来实现 Users/UserProvider $apiToken,然后系统将检查数据库条目是否与请求中的令牌相对应。但我没有用户。

\n

没有用户应该是可以的,因为在上面的 URL 上,它说:

\n
\n

自助验证护照

\n

如果您不需要检查任何凭据(例如,使用 API\ntokens 时),您可以使用 \nSymfony\\Component\\Security\\Http\\Authenticator\\Passport\\SelfValidatingPassport。\ n此类仅需要 UserBadge 对象和可选的 Passport\nBadges。

\n
\n

但这有点单薄。我该如何“使用”它?

\n

Vin*_*aux 7

好吧,我想我明白了,无论如何,您需要处理一些用户,然后您需要创建一个客户 Userprovider。

这是我的逻辑:

应用\安全\用户提供者:

class UserProvider implements UserProviderInterface, PasswordUpgraderInterface
{
    public function loadUserByIdentifier($identifier): UserInterface
    {
        if ($identifier === 'YOUR_API_KEY') {
            return new User();
        }

        throw new UserNotFoundException('API Key is not correct');
    }
    ...
Run Code Online (Sandbox Code Playgroud)

应用\安全\ApiKeyAuthenticator:

class ApiKeyAuthenticator extends AbstractAuthenticator
{
    private UserProvider $userProvider;

    public function __construct(UserProvider $userProvider)
    {
        $this->userProvider = $userProvider;
    }

    public function supports(Request $request): ?bool
    {
        // allow api docs page
        return trim($request->getPathInfo(), '/') !== 'docs';
    }

    public function authenticate(Request $request): Passport
    {
        $apiToken = $request->headers->get('X-API-KEY');
        if (null === $apiToken) {
            // The token header was empty, authentication fails with HTTP Status
            // Code 401 "Unauthorized"
            throw new CustomUserMessageAuthenticationException('No API token provided');
        }

        return new SelfValidatingPassport(
            new UserBadge($apiToken, function () use ($apiToken) {
                return $this->userProvider->loadUserByIdentifier($apiToken);
            })
        );
    }
Run Code Online (Sandbox Code Playgroud)

它对我有用,我的 API 受到标头中基本 API 密钥的保护。我不知道这是否是最好的方法,但似乎还可以。

并在 security.yaml 中定义:

providers:
    # used to reload user from session & other features (e.g. switch_user)
    app_user_provider:
        id: App\Security\UserProvider
Run Code Online (Sandbox Code Playgroud)


小智 3

您可以使用下一个验证

return new SelfValidatingPassport(
    new UserBadge($apiToken, function() use ($apiToken) {
        // TODO: here you can implement any check
    })
);
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,它完全不可能让它工作,文档操作系统如此混乱且写得不好,它没有告诉任何事情。api 令牌身份验证对我不起作用 (3认同)