Symfony2 保护非活动会话生命周期

Symfony2 guard inactive session lifetime

如果用户会话处于非活动状态达 X 秒,我会尝试使用户会话过期。我找到了很多解决方案来做到这一点,但不适用于非活动会话。

我使用带有 Guard 身份验证的 Symfony2。我实现了 this solution,看起来还不错。但是会话过期,即使用户处于活动状态。我可能错过了什么。使用 Guard 是否有任何特殊性会影响会话时间?

我的验证器 :

<?php

namespace AppBundle\Security;


class TokenAuthenticator extends AbstractGuardAuthenticator
{
    /**
   * @var \Symfony\Component\Routing\RouterInterface
   */
    private $router;
    
    /*
     * Url d'accès au WebService d'authentification
     */
    private $urlWs;
  
    /**
     * Constructeur
     * @param RouterInterface $router
     * @param string $urlWs : Url d'accès au WebService d'authentification
     */
    public function __construct(RouterInterface $router, $urlWs) {
        $this->router = $router;
        $this->urlWs = $urlWs;
    }


    /**
     * Called on every request. Return whatever credentials you want,
     * or null to stop authentication.
     */
    public function getCredentials(Request $request)
    {
        if ($request->getPathInfo() != "/login_check"){
            return;
        }
        
        // What you return here will be passed to getUser() as $credentials
        return [
            'login' => $request->request->get('username'),
            'password' => $request->request->get('password'),
            'request' => $request,
        ];
    }

    /**
     * 
     * @param type $credentials
     * @param UserProviderInterface $userProvider
     * @return User
     */
    public function getUser($credentials, UserProviderInterface $userProvider)
    {
       $login = $credentials['login'];
        
       $user = new User();
       $user->setLogin($login);
       
       return $user;
    }

    public function checkCredentials($credentials, UserInterface $user)
    {        
        $username = $credentials['login'];
        $password = $credentials['password'];           
        try {
                /**********************************
                Call my WebService to control the login password
                If it's ok, I save the returned user in session
                *****************************************/
                
                return true;
            } else {
                throw new CustomUserMessageAuthenticationException($ws_response->messages[0]);
            }               
        }catch(\Exception $e){
            throw $e;
        }  
    }
    

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        $session = $request->getSession();     
        $url = "/";
        return new RedirectResponse($url);
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
        $url = $this->router->generate('loginSf');
        return new RedirectResponse($url);
    }

    /**
     * Called when authentication is needed, but it's not sent
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $url = $this->router->generate('loginSf');
        return new RedirectResponse($url);
    }

    public function supportsRememberMe()
    {
        return false;
    }
}

我的会话处理程序:

<?php

namespace AppBundle\Handler;

class SessionIdleHandler
{

    protected $session;
    protected $securityContext;
    protected $router;
    protected $maxIdleTime;

    public function __construct(SessionInterface $session, SecurityContextInterface $securityContext, RouterInterface $router, $maxIdleTime = 0)
    {
        $this->session = $session;
        $this->securityContext = $securityContext;
        $this->router = $router;
        $this->maxIdleTime = $maxIdleTime;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        if (HttpKernelInterface::MASTER_REQUEST != $event->getRequestType()) {

            return;
        }

        if ($this->maxIdleTime > 0) {

            $this->session->start();
            $lapse = time() - $this->session->getMetadataBag()->getLastUsed();

            if ($lapse > $this->maxIdleTime) {

                $this->securityContext->setToken(null);
                $this->session->getFlashBag()->set('info', 'You have been logged out due to inactivity.');

                $event->setResponse(new RedirectResponse($this->router->generate('loginSf')));
            }
        }
    }

}

service.yml:

services:
    my.handler.session_idle:
        class: AppBundle\Handler\SessionIdleHandler
        arguments: ["@session", "@security.context", "@router", %sessionLifeTime%]
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

config.yml:

framework:
    secret:          "%secret%"
    router:
        resource: "%kernel.root_dir%/config/routing.yml"
        strict_requirements: ~
    form:            ~
    csrf_protection: ~
    validation:      { enable_annotations: true }
    templating:
        engines: ['twig']
    default_locale:  "%locale%"
    trusted_hosts:   ~
    trusted_proxies: ~
    session:
        cookie_lifetime: %sessionLifeTime% 
        # handler_id set to null will use default session handler from php.ini
        handler_id:  ~
    fragments:       ~
    http_method_override: true

parameters.yml 我有这个:sessionLifeTime: 0

我也找到了 this option,但它能解决我的问题吗?

The easiest way is to implement this via garbage collection which runs reasonably frequently.

您在 symfony 文档中找到了一段关于空闲时间会话的内容。

http://symfony.com/doc/current/components/http_foundation/session_configuration.html#session-idle-time-keep-alive

感谢您的帮助,

我不明白我做了什么。我已经测试了你的解决方案(所以我评论了我的会话处理程序)将 gc_maxlifetime 放在 config.yml 上,但是我的问题仍然存在。

所以我取消了我的会话处理程序的注释,最后我回到了我之前 post 的代码......现在它可以工作了......

抱歉,我无法解释。我清过很多次缓存,所以我觉得不是这个原因。