我跟随关于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}}
答案 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]);
}
}