Reputation: 1211
Let's start with what's going wrong: I have an acl listener coupled to the "route" event which at first appears to work fine but that will throw a couple of errors after a while. These are the errors:
Fatal error: Uncaught exception 'Zend\Session\Exception\RuntimeException' with message 'Session validation failed'...
Zend\ServiceManager\Exception\ServiceNotCreatedException: An exception was raised while creating "authService"; no instance returned...
Zend\ServiceManager\Exception\ServiceNotCreatedException: An exception was raised while creating "MyAclListener"; no instance returned...
The listener is setup as follows:
class MyAclListener implements ListenerAggregateInterface
{
/** @var AuthenticationServiceInterface */
protected $_authService;
function __construct (
AuthenticationServiceInterface $authService ,
)
{
$this->_authService = $authService;
}
public function attach ( EventManagerInterface $events )
{
$this->listeners[ ] = $events->attach( 'route' , array( $this , 'checkAcl' ) );
}
public function checkAcl( MvcEvent $e ) {
\\\Do Something for which the authService is needed
}
Then, in the module.config.php I have
$config = array(
'service_manager' => array(
'factories' => array(
'MyAclListener' => 'MyAcl\Factory\MyAclListenerFactory'
) ,
) ,
'listeners' => array(
'MyAclListener'
) ,
);
The factory for the listener:
<?php
namespace MyAcl\Factory;
use MyAcl\Listener\MyAclListener;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class AclListenerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
// Finally create the service
return new MyAclListener(
$serviceLocator->get('authService') ,
);
}
}
The Session is setup in Module.php
public function onBootstrap ( MvcEvent $e )
{
$serviceManager = $e->getApplication()->getServiceManager();
$config = $serviceManager->get('Configuration');
$this->initSession( $config['session'] , $serviceManager->get('sessionCache') );
}
public function initSession ( $config , $cache )
{
$sessionConfig = new SessionConfig();
$sessionConfig->setOptions( $config );
$sessionManager = new SessionManager( $sessionConfig );
$saveHandler = new Cache($cache);
$sessionManager->setSaveHandler( $saveHandler );
$sessionManager->getValidatorChain()->attach('session.validate', array(new HttpUserAgent(), 'isValid'));
$sessionManager->getValidatorChain()->attach('session.validate', array(new RemoteAddr(), 'isValid'));
$sessionManager->start();
$sessionManager->regenerateId(true);
}
And these are the relevant configs for the session:
$config = array(
'session' => array(
'cookie_lifetime' => 28800 ,
'remember_me_seconds' => 28800 ,
'use_cookies' => true ,
'cookie_httponly' => true ,
) ,
'caches' => array(
'sessionCache' => array(
'adapter' => array(
'name' => 'memcached' ,
'lifetime' => 604800 ,
'options' => array(
'servers' => array(
array(
'127.0.0.1' , 11211
)
) ,
'namespace' => 'MySessionCache' ,
'liboptions' => array(
'COMPRESSION' => true ,
'binary_protocol' => true ,
'no_block' => true ,
'connect_timeout' => 100
)
) ,
'plugins' => array( 'serializer' )
) ,
) ,
) ,
)
It might also be useful to know that after the error my "identity" is lost and the logged in user was logged out.
So, what am I doing wrong? How do I get rid of these errors? Maybe even: are there better sollutions for setting up an ACL check and my sessions?
UPDATE
I changed the session setup:
In Module.php
public function onBootstrap ( MvcEvent $e )
{
$serviceManager = $e->getApplication()->getServiceManager();
/* session */
$this->expandInitialSessionConfig( $serviceManager , $serviceManager->get( 'sessionCache' ) );
}
public function expandInitialSessionConfig ( $sm , $cache )
{
/** @var \Zend\Session\SessionManager $sessionManager */
$sessionManager = $sm->get( 'Zend\Session\SessionManager' );
$saveHandler = new Cache( $cache );
$sessionManager->setSaveHandler( $saveHandler );
$sessionManager->getValidatorChain()->attach( 'session.validate' , array( new HttpUserAgent() , 'isValid' ) );
$sessionManager->getValidatorChain()->attach( 'session.validate' , array( new RemoteAddr() , 'isValid' ) );
}
In module.config.php
return array(
'session_config' => array(
'cookie_lifetime' => 28800 ,
'remember_me_seconds' => 28800 ,
'use_cookies' => true ,
'cookie_httponly' => true ,
'gc_probability' => 10 ,
'gc_maxlifetime' => 7200 ,
'cookie_domain' => 'mydomain.com' ,
) ,
'service_manager' => array(
'factories' => array(
'Zend\Session\SessionManager' => 'Zend\Session\Service\SessionManagerFactory' ,
'Zend\Session\Config\ConfigInterface' => 'Zend\Session\Service\SessionConfigFactory' ,
) ,
);
And the $sessionManager->regenerateId( true ) was moved so it now only happends on login.
Upvotes: 0
Views: 2422
Reputation: 1211
I seriously doubt this is "best practice", but removing from the constructor of my listener, those depencies (more were added since the original question) that on their turn are dependend on the session solved the issue. I know get them from the ServiceLocator at the first moment I need them in my code and store them in a protected param of my listener class for further use. However, like I said, this isn't proper dependency injection anymore, but at least it works.
function __construct (Logger $_myLog )
{
$this->_myLog = $_myLog;
// removed here: $this->_authService = $authService;
}
Then:
public function checkAcl ( MvcEvent $e )
{
$sm = $e->getApplication()->getServiceManager();
$this->_authService = $sm->get('authService');
....
}
Upvotes: 0
Reputation: 44373
Your ask the ServiceLocator
in your AclListenerFactory
for a authService
but it cannot find anything named like this which causes the second exception.
Because the authService
is not found your factory doesn't return the listener. That is the last exception.
In your code you write:
$serviceLocator->get('authService') ,
The first exception is related to some session validation fail. The cause of all issues lies probably in there. No session validation results probably in no valid authService
thus chaining the other two exceptions.
Where is this authService
registered or created? This is not visible in the code you share currently. And how does this service rely on the "validation" that is failing...
If you solve your session validation issue all will probably be fine.
Upvotes: 1