使用SimplePreAuthenticator和PreAuthenticatedToken时处理短暂令牌的最佳方法

foo*_*bar 6 php security authentication symfony

我正在使用此处所述的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: /
Run Code Online (Sandbox Code Playgroud)

我的身份验证器类看起来像:

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;
    }


}
Run Code Online (Sandbox Code Playgroud)

Symfony2版本:2.5.6

Ser*_*zzo 1

好吧,如果您需要使用会话,您可以lifetime在 config.yml 会话设置下进行设置:

# config.yml
framework:

    session:
        # handler_id set to null will use default session handler from php.ini
        handler_id: ~
        lifetime: 3600
Run Code Online (Sandbox Code Playgroud)

您可以将lifetime值更改为任何以秒为单位的值(默认为 3600 或 1 小时)

另外,您可以尝试配置垃圾收集器

如果这个答案没有帮助,请告诉我。