*/ class Cas extends AbstractAdapter implements EventManagerAwareInterface { /** * @var EventManager */ protected $eventManager; /** * @var ModuleOptions */ protected $options; /** * @var array */ protected $casOptions; /** * @var phpCAS */ protected $casClient; /** * @var LdapPeopleMapper */ protected $ldapPeopleMapper; /** * @var User */ private $userService; /** * @param User $userService */ public function setUserService(User $userService) { $this->userService = $userService; } /** * @var RouteInterface */ private $router; /** * @param RouteInterface $router */ public function setRouter(RouteInterface $router) { $this->router = $router; } public function getStorage() { if (null === $this->storage) { $this->setStorage(new Session()); } return $this->storage; } /** * Réalise l'authentification. * * @param EventInterface $e * @throws UnexpectedValueException * @see ChainableAdapter */ public function authenticate(EventInterface $e) { // NB: Dans la version 3.0.0 de zf-commons/zfc-user, cette méthode prend un EventInterface. // Mais dans la branche 3.x, c'est un AdapterChainEvent ! // Si un jour c'est un AdapterChainEvent qui est attendu, plus besoin de faire $e->getTarget(). $e = $e->getTarget(); // if ($e->getIdentity()) { // return; // } /* DS : modification liée à une boucle infinie lors de l'authentification CAS */ if ($this->isSatisfied()) { $storage = $this->getStorage()->read(); $e->setIdentity($storage['identity']) ->setCode(AuthenticationResult::SUCCESS) ->setMessages(['Authentication successful.']); return; } $config = $this->getOptions()->getCas(); if (!$config) { return; // NB: l'authentification CAS est désactivée ssi le tableau des options est vide } error_reporting($oldErrorReporting = error_reporting() & ~E_NOTICE); $this->getCasClient()->forceAuthentication(); // at this step, the user has been authenticated by the CAS server // and the user's login name can be read with phpCAS::getUser(). $identity = $this->getCasClient(false)->getUser(); error_reporting($oldErrorReporting); $e->setIdentity($identity); $this->setSatisfied(true); $storage = $this->getStorage()->read(); $storage['identity'] = $e->getIdentity(); $this->getStorage()->write($storage); $e->setCode(AuthenticationResult::SUCCESS) ->setMessages(['Authentication successful.']); // recherche de l'individu dans l'annuaire LDAP (il existe forcément puisque l'auth CAS a réussi) $ldapPeople = $this->getLdapPeopleMapper()->findOneByUsername($identity); /* @var $userService User */ $this->userService->userAuthenticated($ldapPeople); } /** * * @param Event $e * @see ChainableAdapter */ public function logout(Event $e) { if (!$this->getOptions()->getCas()) { return; // NB: l'authentification CAS est désactivée ssi le tableau des options est vide } $returnUrl = $this->router->getRequestUri()->setPath($this->router->getBaseUrl())->toString(); $this->getCasClient()->logoutWithRedirectService($returnUrl); } /** * Retourne le client CAS. * * @param boolean $initClient * @return phpCAS * @throws Exception */ public function getCasClient($initClient = true) { if (null === $this->casClient) { $this->casClient = new phpCAS(); } if (!$initClient) { return $this->casClient; } if (null === $this->casOptions) { $config = $this->getOptions()->getCas(); if (!isset($config['connection']['default']['params']) || !$config['connection']['default']['params']) { throw new Exception("Les paramètres de connexion au serveur CAS sont invalides."); } $this->casOptions = $config['connection']['default']['params']; } $options = $this->casOptions; if (array_key_exists('debug', $options) && (bool) $options['debug']) { $this->casClient->setDebug(); } // initialize phpCAS $this->casClient->client($options['version'], $options['hostname'], $options['port'], $options['uri'], true); // no SSL validation for the CAS server $this->casClient->setNoCasServerValidation(); return $this->casClient; } /** * Spécifie le client CAS. * * @param phpCAS $casClient * @return self */ public function setCasClient(phpCAS $casClient) { $this->casClient = $casClient; return $this; } /** * @param ModuleOptions $options */ public function setOptions(ModuleOptions $options) { $this->options = $options; } /** * @return ModuleOptions */ public function getOptions() { // if (!$this->options instanceof ModuleOptions) { // $options = array_merge( // $this->serviceLocator->get('zfcuser_module_options')->toArray(), // $this->serviceLocator->get('unicaen-auth_module_options')->toArray()); // $this->setOptions(new ModuleOptions($options)); // } return $this->options; } /** * get ldap people mapper * * @return LdapPeopleMapper */ public function getLdapPeopleMapper() { return $this->ldapPeopleMapper; } /** * set ldap people mapper * * @param LdapPeopleMapper $mapper * @return self */ public function setLdapPeopleMapper(LdapPeopleMapper $mapper) { $this->ldapPeopleMapper = $mapper; return $this; } /** * Retrieve EventManager instance * * @return EventManagerInterface */ public function getEventManager() { return $this->eventManager; } /** * {@inheritdoc} */ public function setEventManager(EventManagerInterface $eventManager) { $this->eventManager = $eventManager; return $this; } /** * @param RouteInterface $router */ public function reconfigureRoutesForCasAuth(RouteInterface $router) { if(!$router instanceof RouteStackInterface) { return; } $router->addRoutes([ // remplace les routes existantes (cf. config du module) 'zfcuser' => [ 'type' => 'Literal', 'priority' => 1000, 'options' => [ 'route' => '/auth', 'defaults' => [ 'controller' => 'zfcuser', 'action' => 'index', ], ], 'may_terminate' => true, 'child_routes' => [ 'login' => [ 'type' => 'Literal', 'options' => [ 'route' => '/connexion', 'defaults' => [ 'controller' => 'zfcuser', 'action' => 'authenticate', // zappe l'action 'login' ], ], ], 'logout' => [ 'type' => 'Literal', 'options' => [ 'route' => '/deconnexion', 'defaults' => [ 'controller' => 'zfcuser', 'action' => 'logout', ], ], ], ], ], ]); } }