symfony中某些网址的自定义身份验证

时间:2015-02-20 04:38:51

标签: symfony

我跟随关于creating a custom api key authentication for certain urls的文档,但我认为缺少了一些东西。

如果我return;方法::createToken() AuthenticationCredentialsNotFoundException A Token was not found in the SecurityContext.pattern抛出,我会在custom exception controller处理这个问题。异常中的消息是:

^/admin

它仍然迫使我创建一个令牌。我尝试删除配置中的security.yml部分,但没有做任何事情。我希望,对于下面的配置,任何匹配security: encoders: Symfony\Component\Security\Core\User\User: plaintext role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] providers: in_memory_provider: id: app.in_memory_user_repository firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false secured_area: pattern: ^/admin stateless: true simple_preauth: authenticator: app.authenticator access_control: - { path: ^/admin, roles: IS_AUTHENTICATED_ANONYMOUSLY } 的端点都可以选择进行身份验证。 IE浏览器。不需要身份验证,但如果存在api密钥,则会发生身份验证。

我做错了什么?

这是我的<?php class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface, AuthenticationFailureHandlerInterface { /** * {@inheritdoc} */ public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) { $apiKey = $token->getCredentials(); $user = $userProvider->loadUserByUsername("foobar"); return new PreAuthenticatedToken( $user, $apiKey, $providerKey, $user->getRoles() ); } /** * {@inheritdoc} */ public function supportsToken(TokenInterface $token, $providerKey) { return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey; } /** * {@inheritdoc} */ public function createToken(Request $request, $providerKey) { $apiKey = $request->headers->get('Authorization'); if (!$apiKey) { return; } return new PreAuthenticatedToken( 'anon.', $apiKey, $providerKey ); } /** * {@inheritdoc} */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { return new JsonResponse(['errors' => ["Authentication Failed."]], Response::HTTP_FORBIDDEN); } } 文件

{{1}}

我的验证员在这里用以下方式测试:

{{1}}

1 个答案:

答案 0 :(得分:2)

在深入研究一些github问题并尝试了一些事情后想出来。

答案::createToken()方法中返回null,就像文档中所述。您应始终在PreAuthenticatedToken方法中创建::createToken(),并在无法找到用户时在AnonymousToken中创建::authenticateToken()

这是符合预期的验证者

<?php

class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface, AuthenticationFailureHandlerInterface
{
    /**
     * {@inheritdoc}
     */
    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
    {
        $apiKey = $token->getCredentials();

        if (null === $user = $userProvider->loadUserByUsername($apiKey)) {
            return new AnonymousToken($providerKey, 'anon.');
        }

        return new PreAuthenticatedToken(
            $user,
            $apiKey,
            $providerKey,
            $user->getRoles()
        );
    }

    /**
     * {@inheritdoc}
     */
    public function supportsToken(TokenInterface $token, $providerKey)
    {
        return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
    }

    /**
     * {@inheritdoc}
     */
    public function createToken(Request $request, $providerKey)
    {
        $apiKey = $request->headers->get('Authorization');

        return new PreAuthenticatedToken(
            'anon.',
            $apiKey,
            $providerKey
        );
    }

    /**
     * {@inheritdoc}
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        return new JsonResponse(['errors' => ["Authentication Failed."]], Response::HTTP_FORBIDDEN);
    }
}

我的security.yml文件与上述相同。现在,每个请求都不会被对^/admin匹配的端点的身份验证阻止,但我仍然可以检查控制器是否经过身份验证。

<?php

class DefaultController extends Controller
{
    public function indexAction()
    {
        $authenticated = $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY');

        return new JsonResponse(['authenticated' => $authenticated]);
    }
}