Аутентификация Symfony с защитой всегда возвращает & quot; Имя пользователя не найдено. & Quot;

Я знаю, что есть много тем на эту тему, но ни одна из них не помогла мне …

Я работаю над приложением, по которому вы должны отправлять токен доступа в заголовках для каждого запроса.
Я управляю этой безопасностью с Гвардией.

Для моих тестов, когда я отправляю фальшивый токен или когда я его не отправляю, метод start () или onAuthenticationFailure () должен вызываться в зависимости от ситуации.
Но это не работает. У меня одна и та же ошибка каждый раз.
Похоже, эти методы никогда не вызываются.

Авторизация не отправлена

GET /BileMo/web/app_dev.php/api/products/2 HTTP/1.1
Host: localhost:8888
Content-Type: application/json

{
"message": "Username could not be found."}

Недопустимый маркер доступа

GET /BileMo/web/app_dev.php/api/products/2 HTTP/1.1
Host: localhost:8888
Content-Type: application/json
Authorization: *Fake Facebook Token*

{
"message": "Username could not be found."}

вместо:

{
"message": "Authorization required"}

или же

{
"message": "The facebook access token is wrong!"}

При правильном маркере доступа запросы возвращаются пользователю правильно.

Пример запроса:

GET /BileMo/web/app_dev.php/api/products/2 HTTP/1.1
Host: localhost:8888
Content-Type: application/json
Authorization: *Facebook Token*

Вот важные части моего кода:

security.yml

security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512

role_hierarchy:
ROLE_ADMIN:       ROLE_USER
ROLE_SUPER_ADMIN: ROLE_USER

providers:
fos_userbundle:
id: fos_user.user_provider.username_email

api_key_user_provider:
entity:
class: FacebookTokenBundle:User
property: facebook_access_token

firewalls:
api:
pattern: ^/api
stateless: true
anonymous: false
guard:
authenticators:
- AppBundle\Security\FacebookAuthenticator

dev:
pattern:  ^/(_(profiler|wdt)|css|images|js)/
security: false

main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
login_path: /login
check_path: /login_check

oauth:
resource_owners:
facebook:           "/login/check-facebook"login_path:        /login
failure_path:      /login

oauth_user_provider:
#this is my custom user provider, created from FOSUBUserProvider - will manage the
#automatic user registration on your site, with data from the provider (facebook. google, etc.)
service: my_user_provider
logout:       true
anonymous:    truelogin:
pattern:  ^/login$
security: false

remember_me:
secret: "%secret%"lifetime: 31536000 # 365 days in seconds
path: /
domain: ~ # Defaults to the current domain from $_SERVER

access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/api, role: ROLE_USER }

FacebookAuthenticator.php

namespace AppBundle\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class FacebookAuthenticator extends AbstractGuardAuthenticator
{
public function __construct(EntityManager $em)
{
$this->em = $em;
}

/**
* Called when authentication is needed, but it's not sent
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$data = array(
// you might translate this message
'message' => 'Authentication Required'
);

return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
/**
* Called on every request. Return whatever credentials you want to
* be passed to getUser(). Returning null will cause this authenticator
* to be skipped.
*/
public function getCredentials(Request $request)
{
if (!$token = $request->headers->get('Authorization')) {
// No token?
$token = null;
}

// What you return here will be passed to getUser() as $credentials
return array(
'token' => $token,
);
}

public function getUser($credentials, UserProviderInterface $userProvider)
{
$user = $this->em->getRepository('FacebookTokenBundle:User')
->findOneBy(array('facebook_access_token' => $credentials));
return $user;

}

public function checkCredentials($credentials, UserInterface $user)
{
if ($user->getFacebookAccessToken() === $credentials['token']) {
return true;
}
return new JsonResponse(array('message' => 'The facebook access token is wrong!', Response::HTTP_FORBIDDEN));
}

public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
// on success, let the request continue
return null;
}

public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$data = array(
'message' => strtr($exception->getMessageKey(), $exception->getMessageData())

// or to translate this message
// $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
);

return new JsonResponse($data, Response::HTTP_FORBIDDEN);
}

public function supportsRememberMe()
{
return false;
}
}

1

Решение

Такое поведение ожидается. AbstractGuardAuthenticator имеет слишком общий интерфейс, и вам нужно адаптировать его к вашим потребностям, если хотите.

Например, чтобы иметь ошибку «Требуется авторизация» — вы можете вызвать исключение AuthenticationException внутри методов getCredentials (). Исключение будет поймано в ядре Symfony, и метод start () будет вызван окончательно.

public function getCredentials(Request $request)
{
if (!$request->headers->has('Authorization')) {
throw new AuthenticationException();
}
...
}

Метод onAuthenticationFailure () обычно используется для перенаправления пользователя на страницу входа в случае неправильных учетных данных. В случае использования ключа API в заголовке эта функциональность не нужна. Также в текущей реализации, как отделить, когда «ключ API не правильный» и когда «пользователь не найден»?

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]