У меня есть серверный API, разработанный с Symfony2, и теперь я пытаюсь пройти аутентификацию.
Поэтому я использую этот файервол и 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;
}
}
Мои проблемы в деталях:
loadUserByUsername
необходимо найти сущность пользователя путем поиска имени пользователя. Но из этого класса у меня нет доступа к базе данных. Я нашел примеры с использованием статического метода User::find()
но такого метода нет, и Entity — модель MVC — также не имеет доступа к базе данных. Как вывести пользователя из базы данных?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?)
Других решений пока нет …