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 文档中找到了一段关于空闲时间会话的内容。
感谢您的帮助,
我不明白我做了什么。我已经测试了你的解决方案(所以我评论了我的会话处理程序)将 gc_maxlifetime 放在 config.yml 上,但是我的问题仍然存在。
所以我取消了我的会话处理程序的注释,最后我回到了我之前 post 的代码......现在它可以工作了......
抱歉,我无法解释。我清过很多次缓存,所以我觉得不是这个原因。
如果用户会话处于非活动状态达 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 文档中找到了一段关于空闲时间会话的内容。
感谢您的帮助,
我不明白我做了什么。我已经测试了你的解决方案(所以我评论了我的会话处理程序)将 gc_maxlifetime 放在 config.yml 上,但是我的问题仍然存在。
所以我取消了我的会话处理程序的注释,最后我回到了我之前 post 的代码......现在它可以工作了......
抱歉,我无法解释。我清过很多次缓存,所以我觉得不是这个原因。