簡體   English   中英

當我使用AuthTokenAuthenticator(symfony 3)時返回JsonResponse

[英]Return JsonResponse when i use an AuthTokenAuthenticator (symfony 3)

我指定從Symfony開始。 我想創建帶有令牌的API(沒有FOSRestBundle)作為身份驗證的手段。

我針對此設置遵循了不同的教程。 我想要的是當類“ AuthTokenAuthenticator”遇到錯誤時,返回的是json,而不是html視圖。

這是我的腳本:

AuthTokenAuthenticator

namespace AppBundle\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpFoundation\JsonResponse;

class AuthTokenAuthenticator implements 
SimplePreAuthenticatorInterface, AuthenticationFailureHandlerInterface
{

const TOKEN_VALIDITY_DURATION = 12 * 3600;

protected $httpUtils;

public function __construct(HttpUtils $httpUtils)
{
    $this->httpUtils = $httpUtils;
}

public function createToken(Request $request, $providerKey)
{

    //$targetUrlToken = '/auth-tokens'; // login
    //$targetUrlUser = '/users/create'; // create account

    /*if ($request->getMethod() === "POST" && $this->httpUtils->checkRequestPath($request, $targetUrlUser) || $request->getMethod() === "POST" && $this->httpUtils->checkRequestPath($request, $targetUrlToken) ) {
        return;
    }*/

    $authTokenHeader = $request->headers->get('X-Auth-Token');

    if (!$authTokenHeader) {
        //return new JsonResponse(array("error" => 1, "desc" => "INVALID_TOKEN", "message" => "X-Auth-Token header is required"));
       throw new BadCredentialsException('X-Auth-Token header is required');


    }

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

public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
    if (!$userProvider instanceof AuthTokenUserProvider) {
        throw new \InvalidArgumentException(
            sprintf(
                'The user provider must be an instance of AuthTokenUserProvider (%s was given).',
                get_class($userProvider)
                )
            );
    }

    $authTokenHeader = $token->getCredentials();
    $authToken = $userProvider->getAuthToken($authTokenHeader);

    if (!$authToken || !$this->isTokenValid($authToken)) {
        throw new BadCredentialsException('Invalid authentication token');
    }

    $user = $authToken->getUser();
    $pre = new PreAuthenticatedToken(
        $user,
        $authTokenHeader,
        $providerKey,
        $user->getRoles()
        );

    $pre->setAuthenticated(true);

    return $pre;
}

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

/**
 * Vérifie la validité du token
 */
private function isTokenValid($authToken)
{
    return (time() - $authToken->getCreatedAt()->getTimestamp()) < self::TOKEN_VALIDITY_DURATION;
}

public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{

    throw $exception;
}
}

這是我不通知令牌時的錯誤返回:

<!DOCTYPE html>
<html>
<head>
<title>    X-Auth-Token header is required (500 Internal Server Error)

我如何獲得返回的json響應? 如果我嘗試返回新的JsonResponse(array(“ test” =>“ KO”))(簡單示例),則會收到此錯誤:

<title>    Type error: Argument 1 passed to Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager::authenticate() must be an instance of Symfony\Component\Security\Core\Authentication\Token\TokenInterface, instance of Symfony\Component\HttpFoundation\JsonResponse given, called in /Users/mickaelmercier/Desktop/workspace/api_monblocrecettes/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php on line 101 (500 Internal Server Error)

您可以創建自己的錯誤處理程序。 它是事件偵聽器或訂戶,它偵聽kernel.exception ,當它向事件添加響應時,事件傳播將停止,因此不會觸發默認錯誤處理程序。

它可能看起來像這樣:

<?php declare(strict_types = 1);

namespace App\EventSubsbscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\KernelEvents;

final class ExceptionToJsonResponseSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::EXCEPTION => 'onKernelException',
        ];
    }

    public function onKernelException(GetResponseForExceptionEvent $event): void
    {
        // Skip if request is not an API-request
        $request = $event->getRequest();
        if (strpos($request->getPathInfo(), '/api/') !== 0) {
            return;
        }
        $exception = $event->getException();
        $error = [
            'type' => $this->getErrorTypeFromException($exception),
            // Warning! Passing the exception message without checks is insecure.
            // This will potentially leak sensitive information.
            // Do not use this in production!
            'message' => $exception->getMessage(),
        ];
        $response = new JsonResponse($error, $this->getStatusCodeFromException($exception));
        $event->setResponse($response);
    }

    private function getStatusCodeFromException(\Throwable $exception): int
    {
        if ($exception instanceof HttpException) {
            return $exception->getStatusCode();
        }

        return 500;
    }

    private function getErrorTypeFromException(\Throwable $exception): string
    {
        $parts = explode('\\', get_class($exception));

        return end($parts);
    }
}

ApiPlatform像這樣提供了自己的異常偵聽器,它是更高級的,如果您需要“更好”的異常響應,可以進行研究。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM