在TokenStorage而不是403或401中找不到Token的安全性抛出500异常

时间:2015-12-20 04:05:03

标签: php security symfony

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

  

security.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;
    }
}

RestUserToken 就像AbstractToken一样简单,没有其他逻辑。

api_key_user_provider 是由apikey的{​​{1}}属性标识的标准实体提供商

RestUserFactory 里面也没有额外的魔法,就像在官方文档中那样

1 个答案:

答案 0 :(得分:2)

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将产生HTTP 401(如果您查看异常的源代码,您将会理解。)

对于HTTP 403,您可以改为使用Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException