我正在使用此处所述的SimpleAuthentication功能:http://symfony.com/doc/2.6/cookbook/security/api_key_authentication.html
目的是通过作为查询(get)参数或标头传递的标记字符串提供身份验证.这个令牌,我们称之为TemporaryAccessToken以避免与Sf2令牌混淆,由控制器生成,通过电子邮件发送给用户(此处未描述),并且应该在有限的时间内可用(valid_until
\DateTime
专用实体中有一列) ).
对于记录,当simple_user_account
第一次验证过程如下所示访问受保护的页面(通过防火墙)时:
SimplePreAuthenticationListener被触发
基本上是电话 MyAuthenticator->createToken()
然后调用 AuthenticationManager->authenticate()
,调用 MyAuthenticator->authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
问题是:一旦用户通过身份验证,并且因为我stateless: false
在防火墙配置中使用,就不会再次触发身份验证过程,因为会话中已经存在有效的Sf2令牌.
我看到2个逻辑解决方案,但我无法弄清楚如何正确地做到这一点:
使会话有效,直到设置到我的TemporaryAccessToken.valid_until
列中的日期.有没有办法实现"原生"?(我看到remember_me
防火墙有一个lifetime
参数)
或者,能够重新检查TemporaryAccessToken有效性(请参阅if( $accessToken && $accessToken->isValid() )
我的身份验证器中的行)
app/config/security.yml
firewalls: simple_user_account: pattern: ^/account/access stateless: false simple_preauth: authenticator: app.security.simple_user_authenticator logout: path: /logout_simple target: /
我的身份验证器类看起来像:
class SimpleUserAuthenticator implements SimplePreAuthenticatorInterface, AuthenticationFailureHandlerInterface
{
/**
* @var AccessTokenManager
*/
private $accessTokenManager;
/**
* SimpleUserAuthenticator constructor.
* @param AccessTokenManager $accessTokenManager
*/
public function __construct(AccessTokenManager $accessTokenManager)
{
$this->accessTokenManager = $accessTokenManager;
}
public function createToken(Request $request, $providerKey)
{
$TemporaryAccessToken = $request->query->get('simple_user_token');
if (!$TemporaryAccessToken) {
throw new BadCredentialsException('No simple_user token found');
}
return new PreAuthenticatedToken(
'anonymous',
$TemporaryAccessToken,
$providerKey
);
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
if( $token->getUser() instanceof SimpleUser )
{
$newToken = new PreAuthenticatedToken(
$token->getUser(),
$token->getCredentials(),
$providerKey,
array('ROLE_USER')
);
return $newToken;
}
$accessToken = $this->accessTokenManager->getRepository()->findOneByToken($token->getCredentials());
if( $accessToken && $accessToken->isValid() )
{
$user = $userProvider->loadUserByUsername($accessToken->getAccount()->getEmailCanonical());
$newToken = new PreAuthenticatedToken(
$user,
$token->getCredentials(),
$providerKey,
array('ROLE_USER')
);
return $newToken;
}
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$response = new RedirectResponse(
'/login'
);
return $response;
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
}
}
Symfony2版本:2.5.6