Аутентификация пользователя и API с помощью токена / ключа

У меня есть серверный API, разработанный с Symfony2, и теперь я пытаюсь пройти аутентификацию.

  1. Приложение клиент / мобильное устройство должно пройти аутентификацию с помощью ключа API
  2. Пользователь, который использует приложение, должен пройти аутентификацию по электронной почте + пароль и получить access_token

Поэтому я использую этот файервол и apikey authenticator

firewalls:
login:
pattern:  ^/login$
security: false

secured_area:
pattern: ^/
stateless: true
simple_preauth:
authenticator: apikey_authenticator

Аутентификатор ключа Api

namespace Rental\APIBundle\Security;

use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface    {
protected $userProvider;

public function __construct(ApiKeyUserProvider $userProvider)
{
$this->userProvider = $userProvider;
}

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

//$apiKey = $request->query->get('apikey');
// use test value
$apiKey = "234234234";

if (!$apiKey) {
throw new BadCredentialsException('No API key found');
}

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

public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
$apiKey = $token->getCredentials();
$username = $this->userProvider->getUsernameForApiKey($apiKey);

if (!$username) {
throw new AuthenticationException(
sprintf('API Key "%s" does not exist.', $apiKey)
);
}

$user = $this->userProvider->loadUserByUsername($username);

return new PreAuthenticatedToken(
$user,
$apiKey,
$providerKey,
$user->getRoles()
);
}

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

До этого момента проблем нет. Теперь этот класс использует методы следующего класса

namespace Rental\APIBundle\Security;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;

class ApiKeyUserProvider implements UserProviderInterface {
public function getUsernameForApiKey($apiKey)
{
// Look up the username based on the token in the database
// use test value
$username = "Alex";

return $username;
}

public function loadUserByUsername($username)
{
// return User by Username
}

public function refreshUser(UserInterface $user)
{
// code
}

public function supportsClass($class)
{
return 'Symfony\Component\Security\Core\User\User' === $class;
}
}

Мои проблемы в деталях:

  1. Метод loadUserByUsername необходимо найти сущность пользователя путем поиска имени пользователя. Но из этого класса у меня нет доступа к базе данных. Я нашел примеры с использованием статического метода User::find() но такого метода нет, и Entity — модель MVC — также не имеет доступа к базе данных. Как вывести пользователя из базы данных?
  2. Я хочу аутентифицировать сначала само приложение для общего доступа к API, а затем пользователя для личной информации и ограниченных прав редактирования. Когда пользователь вошел в систему по электронной почте и паролю и данные были сохранены, например, в UsernamePasswortToken, как следующий вызов из того же клиента может получить доступ к данным с помощью access_token. Сеанс не влияет на эти AJAX HTTP-запросы.

3

Решение

1.
Вы должны использовать Dependency Injection для него и внедрить менеджер сущностей в вашем провайдере.

 your_api_key_user_provider:
class:     Rental\APIBundle\Security\ApiKeyUserProvider
arguments: ["@doctrine.orm.entity_manager"]
apikey_authenticator:
class:     Rental\APIBundle\Security\ApiKeyAuthenticator
arguments: [""@your_api_key_user_provider"]

После этого добавьте его в провайдера:

    use Doctrine\ORM\EntityManager;

class ApiKeyUserProvider implements UserProviderInterface {

protected $em;

public function __construct(EntityManager $em){
$this->em = $entityManager;
}
//... Now you have access to database

}

2. Ajax может отправлять куки, а php может работать с этими запросами, как с обычными сеансами и сессиями. Убедитесь, что ваш запрос отправляет куки (см. Почему метод jaquery .ajax () не отправляет мой сеансовый cookie?)

2

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

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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector