Rev 2157 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php// Remplacement de apache_request_headers pour les vieux serveurs// http://stackoverflow.com/questions/2916232/call-to-undefined-function-apache-request-headersif(!function_exists('apache_request_headers')) {function apache_request_headers() {// Based on: http://www.iana.org/assignments/message-headers/message-headers.xml#perm-headers$arrCasedHeaders = array(// HTTP'Dasl' => 'DASL','Dav' => 'DAV','Etag' => 'ETag','Mime-Version' => 'MIME-Version','Slug' => 'SLUG','Te' => 'TE','Www-Authenticate' => 'WWW-Authenticate',// MIME'Content-Md5' => 'Content-MD5','Content-Id' => 'Content-ID','Content-Features' => 'Content-features',);$arrHttpHeaders = array();foreach($_SERVER as $strKey => $mixValue) {if('HTTP_' !== substr($strKey, 0, 5)) {continue;}$strHeaderKey = strtolower(substr($strKey, 5));if(0 < substr_count($strHeaderKey, '_')) {$arrHeaderKey = explode('_', $strHeaderKey);$arrHeaderKey = array_map('ucfirst', $arrHeaderKey);$strHeaderKey = implode('-', $arrHeaderKey);}else {$strHeaderKey = ucfirst($strHeaderKey);}if(array_key_exists($strHeaderKey, $arrCasedHeaders)) {$strHeaderKey = $arrCasedHeaders[$strHeaderKey];}$arrHttpHeaders[$strHeaderKey] = $mixValue;}return $arrHttpHeaders;}}// Attention bien v�rifier la pr�sence des variables suivantes :// IDEN_UTILISE_SSO, IDEN_URL_SSO, IDEN_COOKIE_SSO, IDEN_SSO_SYNC// dans le fichier iden_config.inc.phpclass identificationSso {/*** si la valeur est vraiment vide, le cookie n'est pas posé, alors on met* une valeur vide pas vide :)*/public static $VALEUR_JETON_VIDE = "jeton-vide";protected $cookie_mandataire = "";/** le cookie qui dure jusqu'à Vladivostok, si synchro partielle seulement */protected $duree_cookie_mandataire;/*** lorsqu'appelé par un client non-navigateur (qui n'envoie et ne reçoit pas* de cookies), permet de ne pas rediriger en boucle, en fournissant le* paramètre GET "non_interactif"*/protected $mode_non_interactif = false;/** voir IDEN_SSO_SYNC dans iden_config.inc.php */protected $synchro_complete;protected $annuaire_url = '';protected $bdd_annuaire = '';protected $table_annuaire = '';protected $champ_login = '';protected $champ_mdp = '';protected $communs_papyrus = null;public function __construct() {$this->communs_papyrus = $GLOBALS['_GEN_commun'];$this->cookie_mandataire = IDEN_COOKIE_SSO;$this->auth_header = IDEN_HEADER_SSO;$this->annuaire_url = IDEN_URL_SSO;$this->synchro_complete = IDEN_SSO_SYNC;// gestion des clients qui ne gèrent pas les cookies (file_get_contents...)if (isset($_GET['non_interactif'])) {$this->mode_non_interactif = true;}// si on est en mode synchro complète, on vérifie périodiquement l'état// du SSO, en utilisant un cookie qui ne dure pas jusqu'à Vladivostok$this->duree_cookie_mandataire = 3600 * 24 * 365;if ($this->synchro_complete === true) {$this->duree_cookie_mandataire = 180; // une fois toutes les trois minutes, à cause des zozos qui sont pas à l'heure}// c'est moche mais je n'ai pas trouv� plus simple pour r�cuperer la table annuaire en cours// d'utilisation pour le site actuel (la bdd annuaire est la derni�re partie du dsn)$dsn_annuaire = $this->communs_papyrus['info_auth_bdd']->gsab_dsn;$dsn_annuaire = explode('/', $dsn_annuaire);$this->bdd_annuaire = end($dsn_annuaire);$this->table_annuaire = $this->communs_papyrus['info_auth_bdd']->gsab_nom_table;$this->champ_login = $this->communs_papyrus['info_auth_bdd']->gsab_nom_champ_login;$this->champ_mdp = $this->communs_papyrus['info_auth_bdd']->gsab_nom_champ_mdp;}// http://stackoverflow.com/questions/1251582/beautiful-way-to-remove-get-variables-with-php?lq=1protected function supprimerUrlVar($url, $var) {return rtrim(preg_replace('/([?&])'.$var.'=[^&]*(&|$)/','$1',$url), '&?');}/*** Se connecte au SSO : redirige vers le service d'authentification, qui pose* le cookie tb_auth, puis re-redirige vers Papyrus avec le jeton en GET, puis* Papyrus stocke ce jeton dans son cookie mandataire, puis se re-redirige* vers lui-même pour éliminer le paramètre GET de l'URL (ouf !)*/public function connecterEtRediriger() {//echo "JE CONNECTE<br/>";// sauvegarde de l'URL courante$url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];$params = 'login='.$_POST['username'].'&password='.$_POST['password'].'&redirect_url='.urlencode($url_redirect);$connexion_url = $this->annuaire_url."connexion?".$params;// redirection vers l'annuaire, qui va nous connecter au SSO et nous// renvoyer un jeton en GETheader('Location: '.$connexion_url);exit;}/*** Se déconnecte du SSO : redirige vers le service d'authentification, qui* supprime le cookie tb_auth, puis re-redirige vers Papyrus avec un jeton* vide en GET; Papyrus stocke ce jeton vide dans son cookie mandataire,* puis se re-redirige vers lui-même pour éliminer le paramètre GET de l'URL*/public function deconnecterEtRediriger() {//echo "JE DECONNECTE<br/>";// sauvegarde de l'URL courante$url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];$url_redirect = $this->supprimerUrlVar($url_redirect, 'logout');$deconnexion_url = $this->annuaire_url."deconnexion?".'redirect_url='.urlencode($url_redirect);// redirection vers l'annuaire, qui va nous déconnecter du SSO et nous// renvoyer un jeton vide en GETheader('Location: '.$deconnexion_url);exit;}protected function synchroniserDepuisEtatSso() {//echo "JE SYNCHRONISE<br/>";// sauvegarde de l'URL courante$url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];$params = 'redirect_url='.urlencode($url_redirect);$identite_url = $this->annuaire_url."identite?".$params;// redirection vers l'annuaire, qui va nous donner l'état du SSO et nous// renvoyer un jeton en GETheader('Location: '.$identite_url);exit;}/*** Appelée à chaque chargement de page*/public function verifierIdentiteEtRediriger() {// si on fait autre chose qu'un GET, on ne vérifie pas l'identité, car// cela conduirait à une redirection en GET (avec le jeton), qui// supprimerait les données du corps de la requêteif ($_SERVER['REQUEST_METHOD'] == "GET") {// lecture jeton en GET si on vient de l'annuaireif (isset($_GET['Authorization'])) {//echo "Re-Redirection pour éliminer le GET<br/>";// création / mise à jour du cookie mandataire (le jeton peut être// vide en cas de déconnexion)$jetonRecu = $_GET['Authorization'];if ($jetonRecu == '') {$jetonRecu = self::$VALEUR_JETON_VIDE;}$this->setCookieMandataire($jetonRecu);//echo "JETON REÇU: " . $_GET['Authorization'];//echo "JETON POSÉ: "; var_dump($jetonRecu);//exit;// redirection pour éliminer le paramètre GET$url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];$url_redirect = $this->supprimerUrlVar($url_redirect, 'Authorization');//echo "URL Redirect: $url_redirect"; exit;header('Location: ' . $url_redirect);exit;}// une fois qu'on a fait une connexion ou une déconnexion, on se base// sur le cookie mandataire pour gérer l'identité dans Papyrus//var_dump($_COOKIE); echo "<br/>";// lecture cookie mandataire de Papyrus$jeton = null;$cookiePresent = false;if (isset($_COOKIE[$this->cookie_mandataire])) {$cookiePresent = true;$jeton = $_COOKIE[$this->cookie_mandataire];}//echo "Cookie Présent: "; var_dump($cookiePresent);//echo "JETON: "; var_dump($jeton); echo "<br/>";//exit;// s'il y a un cookie, qu'il contienne un jeton valide ou videif ($cookiePresent) {// s'il contient un jeton non-videif ($jeton != self::$VALEUR_JETON_VIDE) {// reconnexion PEAR (l'utilisateur peut avoir changé)//echo "RECONNEXION!<br/>"; exit;$this->deconnexionPear();$this->connexionPear($jeton);// prolonge le cookie de 30 secondes si on est connecté, pour// minimiser les synchros avec le SSO$this->setCookieMandataire($jeton, 30);// si mode synchro partielle, le cookie mandataire dure logntemps,// on rafraîchit donc le jeton pour... euh... on sait jamais :-/if (! $this->synchro_complete) {// appel annuaire / identité avec jeton en GET$infosJson = $this->rafraichirJeton($jeton);$infos = json_decode($infosJson, true);//echo "INFOS: "; var_dump($infos); echo "<br/>";$jetonRafraichi = null;if (isset($infos['token'])) {$jetonRafraichi = $infos['token'];}//echo "JETON Rafraîchi: "; var_dump($jetonRafraichi); echo "<br/>";//exit;// si jeton rafraîchi reçuif ($jetonRafraichi != null) {// màj cookie avec jeton rafraîchi$this->setCookieMandataire($jetonRafraichi);// reconnexion PEAR (l'utilisateur peut avoir changé)$this->deconnexionPear();$this->connexionPear($jetonRafraichi);//exit;} else {// sinon (non connecté ou problème annuaire / jeton)// écriture cookie avec jeton vide$this->setCookieMandataire(self::$VALEUR_JETON_VIDE);// déconnexion PEAR$this->deconnexionPear();}}} else {// déconnexion PEAR ?$this->deconnexionPear();}} else { // sinon (aucun cookie mandataire)// en mode synchro complète, on vérifie chaque minute (lorsque le// cookie mandataire n'est plus présent) si on n'est pas connecté// sur le SSO, sauf si on est en mode non interactifif ($this->synchro_complete && (! $this->mode_non_interactif)) {$this->synchroniserDepuisEtatSso();}}}}protected function setCookieMandataire($valeur, $duree=null) {if ($duree === null) {$duree = $this->duree_cookie_mandataire;}setcookie($this->cookie_mandataire, $valeur, time() + $duree);}/*** Connecte l'utilisateur à Papyrus avec le système traditionnel fourni par PEAR*/protected function connexionPear($jeton) {$jeton_decode = $this->decoderToken($jeton);// R�cup�ration du mot de passe pour remplir les infos de l'objet PEAR Auth$requete = 'SELECT '.$this->champ_mdp.' '.'FROM '.$this->bdd_annuaire.'.'.$this->table_annuaire.' '.'WHERE '.$this->champ_login.' = "'.$jeton_decode['sub'].'" ';// TODO: normalement �a n'est jamais le cas mais que fait t'on si l'utilisateur n'existe pas// dans notre base de donn�es ? (au pire il ne sera pas connect�)$this->communs_papyrus['pear_auth']->username = $jeton_decode['sub'];$this->communs_papyrus['pear_auth']->password = $this->communs_papyrus['pear_db']->getOne($requete);// Le mot de passe est d�j� crypt� dans la bdd donc il faut indiquer � pear de ne pas le re crytperif (isset($this->communs_papyrus['pear_auth']->storage_options)) {$this->communs_papyrus['pear_auth']->storage_options['cryptType'] = 'none';}if (isset($this->communs_papyrus['pear_auth']->storage->options)) {$this->communs_papyrus['pear_auth']->storage->options['cryptType'] = 'none';}// si on fait pas ça, ça marche pas (régénération de session apparemment)//$this->communs_papyrus['pear_auth']->setAuth($jeton_decode['sub']);}/*** Supprime tout ce qui a trait à PEAR afin de déconnecter l'utilisateur du* système d'authentification traditionnel de Papyrus*/protected function deconnexionPear() {$this->communs_papyrus['pear_auth']->logout();$cookie_persistant_nom = session_name().'-memo';$cookie_utilisateur_nom = session_name().'-utilisateur';// Destruction du cookie de session de Papyrus : est ce utile?setcookie(session_name(), session_id(), time()-3600, '/');// Destruction du cookie de permanence de l'identitification de Papyrussetcookie($cookie_persistant_nom, '', time()-3600, '/');setcookie($cookie_utilisateur_nom, '', time()-3600, '/');}/*** Fournit un jeton à l'annuaire (jeton provenant du cookie mandataire* de Papyrus), le fait rafraîchir puis met à jour le cookie mandataire avec* le jeton rafraîchi*/protected function rafraichirJeton($jeton) {$identiteServiceURL = $this->annuaire_url . "identite";$identiteServiceURL .= "?token=" . $jeton;//echo "URL: $identiteServiceURL<br/>";$ch = curl_init($identiteServiceURL);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);$jetonRafraichi = curl_exec($ch);//var_dump($jetonRafraichi);//var_dump(curl_error($ch)); exit;return $jetonRafraichi;}protected function decoderToken($token) {$token_parts = explode('.', $token);return json_decode(base64_decode($token_parts[1]), true);}}?>