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

时间:2016-06-15 07:19:44

标签: php symfony session guard

如果用户会话处于非活动状态X秒,我会尝试使用户会话失效。我找到了许多解决方案,但不适用于非活动会话。

我使用Symfony2和Guard Authentification。我已经实施了this solution,这似乎并不坏。但即使用户处于活动状态,会话也会过期。我可能会错过一些东西使用Guard可能会影响会话时间吗?

我的身份验证器

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

我的会话处理程序:     

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,但这是解决我问题的方法吗?

你能帮帮我吗?感谢' S

2 个答案:

答案 0 :(得分:0)

  

最简单的方法是通过合理频繁运行的垃圾收集来实现这一点。

你在symfony doc上有一段关于空闲时间的段落。

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

答案 1 :(得分:0)

感谢您的帮助,

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

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

抱歉,我无法解释。我已多次清除缓存,所以我认为这不是原因。