在TokenStorage而不是403或401中找不到具有Token的Security throwns 500异常


Security throwns 500 exception with Token was not found in TokenStorage instead of 403 or 401

我通过ApiKey进行授权,如果没有提供授权数据,我想获得401 Unauthorized,如果授权数据无效,我想获取403 Forbidden。但我在这两种情况下都得了500 Internal Server Error

安全性。yml

security:
    providers:
        api_key_user_provider:
            entity:
                class: RestBundle:RestUser
                property: apikey
    firewalls:
        rest_api_area:
            pattern: ^/api
            stateless: true
            rest_auth:
                header: x-apikey
            provider: api_key_user_provider
    access_control:
        - { path: ^/api, roles: ROLE_REST_USER }

RestUserListener.php:

class RestUserListener implements ListenerInterface
{
    protected $tokenStorage;
    protected $authenticationManager;
    private $header;
    function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, $header)
    {
        $this->tokenStorage = $tokenStorage;
        $this->authenticationManager = $authenticationManager;
        $this->header = $header;
    }
    public function handle(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $apikey = $request->headers->get($this->header);
        if (!$apikey) return;
        $token = new RestUserToken();
        $token->setUser($apikey);
        $authToken = $this->authenticationManager->authenticate($token);
        $this->tokenStorage->setToken($authToken);
        return;
    }
}

RestUserAuthenticationProvider.php:

class RestUserAuthenticationProvider implements AuthenticationProviderInterface
{
    private $userProvider;
    public function __construct(UserProviderInterface $userProvider)
    {
        $this->userProvider = $userProvider;
    }
    public function authenticate(TokenInterface $token)
    {
        $user = $this->userProvider->loadUserByUsername($token->getUsername());
        if ($user)
        {
            $authenticatedToken = new RestUserToken($user->getRoles());
            $authenticatedToken->setUser($user);
            return $authenticatedToken;
        }
        throw new AuthenticationException("Apikey not found.");
    }
    public function supports(TokenInterface $token)
    {
        return $token instanceof RestUserToken;
    }
}

RestUserTokenAbstractToken一样简单,没有额外的逻辑。

api_key_user_provider是由RestUserapikey属性标识的标准实体提供者

RestUserFactory内部也没有其他魔法,就像官方文档

中一样

RestUserListener::handle()方法应该处理返回HTTP 401或HTTP 403的情况。

仅仅拥有return;不会实现这一点。

在我写的一个类似的应用程序中,我这样做了:

use Symfony'Component'HttpKernel'Exception'UnauthorizedHttpException;
//
...
//
public function handle(GetResponseEvent $event)
{
    $request = $event->getRequest();
    if ( /* something invalid here, so error */ ) {
        $context = $request->getHost();
        throw new UnauthorizedHttpException(
            "Basic realm='"$context'"",
            'Please authenticate correctly or any other message here'
        );
    }
}

抛出UnauthorizedHttpException将导致HTTP401(如果查看异常的源代码,您就会明白)。

对于HTTP 403,您可以改用Symfony'Component'HttpKernel'Exception'AccessDeniedHttpException