【发布时间】:2014-12-17 01:04:39
【问题描述】:
我有一个使用 Symfony2 开发的服务器端 API,现在我尝试进行身份验证。
- 客户端/移动设备应用程序必须使用 API 密钥进行身份验证
- 使用该应用程序的用户必须使用电子邮件 + 密码进行身份验证并获得 access_token
因此我使用了这个防火墙和 apikey 验证器
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()的示例,但没有这样的方法,并且实体(MVC 的模型)也无法访问数据库。如何将用户从数据库中取出? - 我想首先对 APP 本身进行身份验证以获取一般 API 访问权限,然后对用户进行身份验证以获取个人信息和有限的编辑权限。当用户通过电子邮件和密码登录时,数据已保存,例如在 UsernamePasswortToken 中,来自同一客户端的下一次呼叫如何使用 access_token 访问数据。会话对这些 AJAX HTTP 请求没有影响。
【问题讨论】:
标签: php api rest symfony access-token