Subversion Repositories Applications.wikini

Rev

Rev 66 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 66 Rev 75
1
<?php
1
<?php
2
 
2
 
3
// Remplacement de apache_request_headers pour les vieux serveurs
3
// Remplacement de apache_request_headers pour les vieux serveurs
4
// http://stackoverflow.com/questions/2916232/call-to-undefined-function-apache-request-headers
4
// http://stackoverflow.com/questions/2916232/call-to-undefined-function-apache-request-headers
5
if(!function_exists('apache_request_headers')) {
5
if(!function_exists('apache_request_headers')) {
6
	function apache_request_headers() {
6
	function apache_request_headers() {
7
		// Based on: http://www.iana.org/assignments/message-headers/message-headers.xml#perm-headers
7
		// Based on: http://www.iana.org/assignments/message-headers/message-headers.xml#perm-headers
8
		$arrCasedHeaders = array(
8
		$arrCasedHeaders = array(
9
				// HTTP
9
				// HTTP
10
				'Dasl'             => 'DASL',
10
				'Dasl'             => 'DASL',
11
				'Dav'              => 'DAV',
11
				'Dav'              => 'DAV',
12
				'Etag'             => 'ETag',
12
				'Etag'             => 'ETag',
13
				'Mime-Version'     => 'MIME-Version',
13
				'Mime-Version'     => 'MIME-Version',
14
				'Slug'             => 'SLUG',
14
				'Slug'             => 'SLUG',
15
				'Te'               => 'TE',
15
				'Te'               => 'TE',
16
				'Www-Authenticate' => 'WWW-Authenticate',
16
				'Www-Authenticate' => 'WWW-Authenticate',
17
				// MIME
17
				// MIME
18
				'Content-Md5'      => 'Content-MD5',
18
				'Content-Md5'      => 'Content-MD5',
19
				'Content-Id'       => 'Content-ID',
19
				'Content-Id'       => 'Content-ID',
20
				'Content-Features' => 'Content-features',
20
				'Content-Features' => 'Content-features',
21
		);
21
		);
22
		$arrHttpHeaders = array();
22
		$arrHttpHeaders = array();
23
 
23
 
24
		foreach($_SERVER as $strKey => $mixValue) {
24
		foreach($_SERVER as $strKey => $mixValue) {
25
			if('HTTP_' !== substr($strKey, 0, 5)) {
25
			if('HTTP_' !== substr($strKey, 0, 5)) {
26
				continue;
26
				continue;
27
			}
27
			}
28
 
28
 
29
			$strHeaderKey = strtolower(substr($strKey, 5));
29
			$strHeaderKey = strtolower(substr($strKey, 5));
30
 
30
 
31
			if(0 < substr_count($strHeaderKey, '_')) {
31
			if(0 < substr_count($strHeaderKey, '_')) {
32
				$arrHeaderKey = explode('_', $strHeaderKey);
32
				$arrHeaderKey = explode('_', $strHeaderKey);
33
				$arrHeaderKey = array_map('ucfirst', $arrHeaderKey);
33
				$arrHeaderKey = array_map('ucfirst', $arrHeaderKey);
34
				$strHeaderKey = implode('-', $arrHeaderKey);
34
				$strHeaderKey = implode('-', $arrHeaderKey);
35
			}
35
			}
36
			else {
36
			else {
37
				$strHeaderKey = ucfirst($strHeaderKey);
37
				$strHeaderKey = ucfirst($strHeaderKey);
38
			}
38
			}
39
 
39
 
40
			if(array_key_exists($strHeaderKey, $arrCasedHeaders)) {
40
			if(array_key_exists($strHeaderKey, $arrCasedHeaders)) {
41
				$strHeaderKey = $arrCasedHeaders[$strHeaderKey];
41
				$strHeaderKey = $arrCasedHeaders[$strHeaderKey];
42
			}
42
			}
43
 
43
 
44
			$arrHttpHeaders[$strHeaderKey] = $mixValue;
44
			$arrHttpHeaders[$strHeaderKey] = $mixValue;
45
		}
45
		}
46
		return $arrHttpHeaders;
46
		return $arrHttpHeaders;
47
	}
47
	}
48
}
48
}
49
 
49
 
50
class identificationSso {
50
class identificationSso {
51
 
51
 
52
	private $wiki = null;
52
	private $wiki = null;
53
	private $config = null;
53
	private $config = null;
54
 
54
 
55
	private $cookie_tentative_identification = "";
55
	private $cookie_tentative_identification = "";
56
	private $delai_tentative_identification = 60;
56
	private $delai_tentative_identification = 60;
57
	
57
	
58
	private $auth_header = 'Authorization';
58
	private $auth_header = 'Authorization';
59
 
59
 
60
	public function __construct($wiki) {
60
	public function __construct($wiki) {
61
		$this->wiki = $wiki;
61
		$this->wiki = $wiki;
62
		$this->config = $wiki->config;
62
		$this->config = $wiki->config;
63
		$this->auth_header = !empty($this->config['sso_auth_header']) ? $this->config['sso_auth_header'] : $this->auth_header;
63
		$this->auth_header = !empty($this->config['sso_auth_header']) ? $this->config['sso_auth_header'] : $this->auth_header;
64
		$this->cookie_tentative_identification = 'wikini_sso_tentative_identification';
64
		$this->cookie_tentative_identification = 'wikini_sso_tentative_identification';
65
	}
65
	}
66
 
66
 
67
	function getToken() {
67
	function getToken() {
68
		// Premier essai, dans le header
68
		// Premier essai, dans le header
69
		$headers = @apache_request_headers();
69
		$headers = @apache_request_headers();
70
		$token = !empty($headers['Authorization']) ? $headers['Authorization'] : null;
70
		$token = !empty($headers['Authorization']) ? $headers['Authorization'] : null;
71
		// Eventuellement, le jeton a pu être passé dans un header non standard, comme dans 
71
		// Eventuellement, le jeton a pu être passé dans un header non standard, comme dans 
72
		// le cas où le header Authorization est supprimé par le mod cgi d'apache
72
		// le cas où le header Authorization est supprimé par le mod cgi d'apache
73
		// Dans ce cas là on vérifie aussi dans un header alternatif si celui ci a été renseigné
73
		// Dans ce cas là on vérifie aussi dans un header alternatif si celui ci a été renseigné
74
		if($token == null && $this->auth_header != 'Authorization') {
74
		if($token == null && $this->auth_header != 'Authorization') {
75
			$token = !empty($headers[$this->auth_header]) ? $headers[$this->auth_header] : null;
75
			$token = !empty($headers[$this->auth_header]) ? $headers[$this->auth_header] : null;
76
		}
76
		}
77
 
77
 
78
		// Sinon dans $_REQUEST ?
78
		// Sinon dans $_REQUEST ?
79
		if($token == null) {
79
		if($token == null) {
80
			$token = !empty($_REQUEST['Authorization']) ? $_REQUEST['Authorization'] : null;
80
			$token = !empty($_REQUEST['Authorization']) ? $_REQUEST['Authorization'] : null;
81
		}
81
		}
82
		
82
		
83
		// Sinon dans $_COOKIE ?
83
		// Sinon dans $_COOKIE ?
84
		if($token == null) {
84
		if($token == null) {
85
			$token = !empty($_COOKIE['tb_auth']) ? $_COOKIE['tb_auth'] : null;
85
			$token = !empty($_COOKIE['tb_auth']) ? $_COOKIE['tb_auth'] : null;
86
		}
86
		}
87
 
87
 
88
		return $token;
88
		return $token;
89
	}
89
	}
90
 
90
 
91
	function decoderToken($token) {
91
	function decoderToken($token) {
92
		$token_parts = explode('.', $token);
92
		$token_parts = explode('.', $token);
93
		return json_decode(base64_decode($token_parts[1]), true);
93
		return json_decode(base64_decode($token_parts[1]), true);
94
	}
94
	}
95
 
95
 
96
	function getPage() {
96
	function getPage() {
97
		return !empty($this->wiki->page) ? $this->wiki->page['tag'] : 'PagePrincipale';
97
		return !empty($this->wiki->page) ? $this->wiki->page['tag'] : 'PagePrincipale';
98
	}
98
	}
99
 
99
 
100
	// http://stackoverflow.com/questions/1251582/beautiful-way-to-remove-get-variables-with-php?lq=1
100
	// http://stackoverflow.com/questions/1251582/beautiful-way-to-remove-get-variables-with-php?lq=1
101
	function supprimerUrlVar($url, $var) {
101
	function supprimerUrlVar($url, $var) {
102
		 return rtrim(preg_replace('/([?&])'.$var.'=[^&]+(&|$)/','$1',$url), '&?');
102
		 return rtrim(preg_replace('/([?&])'.$var.'=[^&]+(&|$)/','$1',$url), '&?');
103
	}
103
	}
104
 
104
 
105
	function getInfosCookie() {
105
	function getInfosCookie() {
106
		$infos = null;
106
		$infos = null;
107
		if(!empty($_COOKIE[$this->cookie_tentative_identification])) {
107
		if(!empty($_COOKIE[$this->cookie_tentative_identification])) {
108
			$infos = json_decode($_COOKIE[$this->cookie_tentative_identification], true);
108
			$infos = json_decode($_COOKIE[$this->cookie_tentative_identification], true);
109
		}
109
		}
110
		return $infos;
110
		return $infos;
111
	}
111
	}
112
 
112
 
113
	function setInfosCookie($infos) {
113
	function setInfosCookie($infos) {
114
		$infos['expire'] = !empty($infos['expire']) ? $infos['expire'] : 0;
114
		$infos['expire'] = !empty($infos['expire']) ? $infos['expire'] : 0;
115
		setcookie($this->cookie_tentative_identification, json_encode($infos), $infos['expire'], $this->wiki->CookiePath);
115
		setcookie($this->cookie_tentative_identification, json_encode($infos), $infos['expire'], $this->wiki->CookiePath);
116
	}
116
	}
117
 
117
 
118
	function verifierEtInsererUtilisateurParJeton($jeton_rafraichi) {
118
	function verifierEtInsererUtilisateurParJeton($jeton_rafraichi) {
119
		if(!empty($jeton_rafraichi['session']) && $jeton_rafraichi['session'] == true) {
119
		if(!empty($jeton_rafraichi['session']) && $jeton_rafraichi['session'] == true) {
120
			$token_decode = $this->decoderToken($jeton_rafraichi['token']);
120
			$token_decode = $this->decoderToken($jeton_rafraichi['token']);
121
			
121
			
122
			$nom_wiki = $token_decode['nomWiki'];
122
			$nom_wiki = $token_decode['nomWiki'];
123
			$courriel = $token_decode['sub'];
123
			$courriel = $token_decode['sub'];
124
			
124
			
125
			$utilisateur_wiki_existe = $this->wiki->LoadAll("SELECT * FROM  ".$this->wiki->config["table_prefix"]."users ".
125
			$utilisateur_wiki_existe = $this->wiki->LoadAll("SELECT * FROM  ".$this->wiki->config["table_prefix"]."users ".
126
					"WHERE ".
126
					"WHERE ".
127
					"name = '".mysql_escape_string($nom_wiki)."' OR ".
127
					"name = '".mysql_escape_string($nom_wiki)."' OR ".
128
					"email = '".mysql_escape_string($courriel)."'");
128
					"email = '".mysql_escape_string($courriel)."'");
129
			
129
			
130
			// pas inscrit ? on l'ajout à la base de données
130
			// pas inscrit ? on l'ajout à la base de données
131
			if(empty($utilisateur_wiki_existe)) {
131
			if(empty($utilisateur_wiki_existe)) {
132
				// mot de passe généré à l'arrache, le mieux serait de trouver celui de tela encodé
132
				// mot de passe généré à l'arrache, le mieux serait de trouver celui de tela encodé
133
				// mais en gérant bien le sso on peut s'en passer car l'utilisateur ne devrait jamais avoir 
133
				// mais en gérant bien le sso on peut s'en passer car l'utilisateur ne devrait jamais avoir 
134
				// à s'identifier par le wiki
134
				// à s'identifier par le wiki
135
				$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
135
				$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
136
				$pass = substr(str_shuffle(str_repeat($pool, 16)), 0, 16);
136
				$pass = substr(str_shuffle(str_repeat($pool, 16)), 0, 16);
137
				
137
				
138
				$this->wiki->Query("insert into ".$this->wiki->config["table_prefix"]."users set ".
138
				$this->wiki->Query("insert into ".$this->wiki->config["table_prefix"]."users set ".
139
						"signuptime = now(), ".
139
						"signuptime = now(), ".
140
						"name = '".mysql_escape_string($token_decode['nomWiki'])."', ".
140
						"name = '".mysql_escape_string($token_decode['nomWiki'])."', ".
141
						"email = '".mysql_escape_string($token_decode['sub'])."', ".
141
						"email = '".mysql_escape_string($token_decode['sub'])."', ".
142
						"password = md5('".mysql_escape_string($pass)."')");
142
						"password = md5('".mysql_escape_string($pass)."')");
143
			} else {
143
			} else {
144
				// Un utilisateur peut déjà s'être inscrit sur le wiki avec un autre nom que son pseudo
144
				// Un utilisateur peut déjà s'être inscrit sur le wiki avec un autre nom que son pseudo
145
				$nom_wiki = $utilisateur_wiki_existe[0]['name'];
145
				$nom_wiki = $utilisateur_wiki_existe[0]['name'];
146
				// s'il existe un enregistrement avec ce mail et un autre avec ce nomWiki on garde celui qui correspond au bon courriel
146
				// s'il existe un enregistrement avec ce mail et un autre avec ce nomWiki on garde celui qui correspond au bon courriel
147
				foreach($utilisateur_wiki_existe as $utilisateur_wiki) {
147
				foreach($utilisateur_wiki_existe as $utilisateur_wiki) {
148
					if($utilisateur_wiki['email'] == $courriel) {
148
					if($utilisateur_wiki['email'] == $courriel) {
149
						  $nom_wiki = $utilisateur_wiki['name'];
149
						  $nom_wiki = $utilisateur_wiki['name'];
150
					}
150
					}
151
				}
151
				}
152
			}
152
			}
153
		}
153
		}
154
 
154
 
155
		return $nom_wiki;
155
		return $nom_wiki;
156
	}
156
	}
157
 
157
 
158
	function recupererIdentiteConnectee() {
158
	function recupererIdentiteConnectee() {
159
		$infos_cookie = $this->getInfosCookie();
159
		$infos_cookie = $this->getInfosCookie();
160
		if($infos_cookie == null || $infos_cookie['tentative_identification'] == false) {	
160
		if($infos_cookie == null || $infos_cookie['tentative_identification'] == false) {	
161
			// peut importe si l'annuaire répond oui ou non, on a fait une tentative d'identification
161
			// peut importe si l'annuaire répond oui ou non, on a fait une tentative d'identification
162
			// et si on a trouvé quelqu'un on ne réésaiera pas jusqu'à la fermeture du navigateur
162
			// et si on a trouvé quelqu'un on ne réésaiera pas jusqu'à la fermeture du navigateur
163
			$infos_cookie = array('tentative_identification' => true, 'expire' => 0);
163
			$infos_cookie = array('tentative_identification' => true, 'expire' => 0);
164
 			$this->setInfosCookie($infos_cookie);
164
 			$this->setInfosCookie($infos_cookie);
165
 
165
 
166
			$annuaire_url = $this->wiki->config['sso_url'].'identite';
166
			$annuaire_url = $this->wiki->config['sso_url'].'identite';
167
			// Attention si le paramètre wiki de l'url est vide, la redirection de retour pose des problèmes
167
			// Attention si le paramètre wiki de l'url est vide, la redirection de retour pose des problèmes
168
			$url = $annuaire_url.'?redirect_url='.urlencode($this->wiki->config['base_url'].$this->getPage());
168
			$url = $annuaire_url.'?redirect_url='.urlencode($this->wiki->config['base_url'].$this->getPage());
169
 
169
 
170
			header('Location: '.$url);
170
			header('Location: '.$url);
171
			exit;
171
			exit;
172
		} else {
172
		} else {
173
			$token = $this->getToken();
173
			$token = $this->getToken();
174
 
174
 
175
			if($token != null) {
175
			if($token != null) {
176
				// On demande à l'annuaire si le jeton est bien valide
176
				// On demande à l'annuaire si le jeton est bien valide
177
				$jeton_rafraichi = json_decode(file_get_contents($this->wiki->config['sso_url'].'rafraichir?token='.$token), true);
177
				$jeton_rafraichi = json_decode(file_get_contents($this->wiki->config['sso_url'].'rafraichir?token='.$token), true);
178
				$nom_wiki = $this->verifierEtInsererUtilisateurParJeton($jeton_rafraichi);
178
				$nom_wiki = $this->verifierEtInsererUtilisateurParJeton($jeton_rafraichi);
179
				$token_decode = $this->decoderToken($jeton_rafraichi['token']);
-
 
180
 
179
 
181
				// dans le pire des cas, si on se déconnecte dans une autre application, on sera déconnecté 
180
				// dans le pire des cas, si on se déconnecte dans une autre application, on sera déconnecté 
182
				// lorsque le jeton expirera
181
				// lorsque le jeton expirera
183
				$infos_cookie = array('tentative_identification' => true, 'expire' => time()+$jeton_rafraichi['duration']);
182
				$infos_cookie = array('tentative_identification' => true, 'expire' => time()+$jeton_rafraichi['duration']);
184
				$this->setInfosCookie($infos_cookie);
183
				$this->setInfosCookie($infos_cookie);
185
 
184
 
186
				$this->wiki->SetUser($this->wiki->LoadUser($nom_wiki));
185
				$this->wiki->SetUser($this->wiki->LoadUser($nom_wiki));
187
			} else {
186
			} else {
188
				// personne n'a été trouvé ? on remplace le cookie par un de durée plus courte 
187
				// personne n'a été trouvé ? on remplace le cookie par un de durée plus courte 
189
				// pour rééssayer dans delai_tentative_identification si on en a pas déjà un
188
				// pour rééssayer dans delai_tentative_identification si on en a pas déjà un
190
				if($infos_cookie['expire'] == 0) { 
189
				if($infos_cookie['expire'] == 0) { 
191
					$infos_cookie['expire'] = time()+$this->delai_tentative_identification;
190
					$infos_cookie['expire'] = time()+$this->delai_tentative_identification;
192
					$this->setInfosCookie($infos_cookie);
191
					$this->setInfosCookie($infos_cookie);
193
				}
192
				}
194
			}
193
			}
195
		}
194
		}
196
	}
195
	}
197
 
196
 
198
	function recupererIdentiteConnecteePourApi() {		
197
	function recupererIdentiteConnecteePourApi() {		
199
		$token = $this->getToken();
198
		$token = $this->getToken();
200
		if($token != null) {
199
		if($token != null) {
201
			// On demande à l'annuaire si le jeton est bien valide
200
			// On demande à l'annuaire si le jeton est bien valide
202
			$jeton_rafraichi = json_decode(file_get_contents($this->wiki->config['sso_url'].'rafraichir?token='.$token), true);
201
			$jeton_rafraichi = json_decode(file_get_contents($this->wiki->config['sso_url'].'rafraichir?token='.$token), true);
203
			$nom_wiki = $this->verifierEtInsererUtilisateurParJeton($jeton_rafraichi);
202
			$nom_wiki = $this->verifierEtInsererUtilisateurParJeton($jeton_rafraichi);
204
			$token_decode = $this->decoderToken($jeton_rafraichi['token']);
-
 
205
			$this->wiki->SetUser($this->wiki->LoadUser($nom_wiki));
203
			$this->wiki->SetUser($this->wiki->LoadUser($nom_wiki));
206
		}
204
		}
207
	}
205
	}
208
 
206
 
209
	function connecterUtilisateur($login, $pass, $url_redirect = null) {
207
	function connecterUtilisateur($login, $pass, $url_redirect = null) {
210
		if(strpos($login, '@') === false) {
208
		if(strpos($login, '@') === false) {
211
			$utilisateur_wiki = $this->wiki->LoadSingle("SELECT email FROM  ".$this->wiki->config["table_prefix"]."users ".
209
			$utilisateur_wiki = $this->wiki->LoadSingle("SELECT email FROM  ".$this->wiki->config["table_prefix"]."users ".
212
			"WHERE name = '".mysql_escape_string($login)."'");
210
			"WHERE name = '".mysql_escape_string($login)."'");
213
 
211
 
214
			$login = !empty($utilisateur_wiki) ? $utilisateur_wiki['email'] : $login;
212
			$login = !empty($utilisateur_wiki) ? $utilisateur_wiki['email'] : $login;
215
			// TODO: si le courriel a changé dans l'annuaire, on devrait mettre à jour les informations 
213
			// TODO: si le courriel a changé dans l'annuaire, on devrait mettre à jour les informations 
216
			// si on a utilisé le nom wiki pour s'identifier mais le flow du programme rend cela complexe
214
			// si on a utilisé le nom wiki pour s'identifier mais le flow du programme rend cela complexe
217
		}
215
		}
218
 
216
 
219
		$url_redirect = ($url_redirect == null) ? $this->wiki->config['base_url'].'PagePrincipale' : $url_redirect;
217
		$url_redirect = ($url_redirect == null) ? $this->wiki->config['base_url'].'PagePrincipale' : $url_redirect;
220
 
218
 
221
		// le cookie de tentative d'identification est remis à zéro pour qu'au rechargement de la page il vérifie l'identité 
219
		// le cookie de tentative d'identification est remis à zéro pour qu'au rechargement de la page il vérifie l'identité 
222
		// connectée du nouvel utilisateur
220
		// connectée du nouvel utilisateur
223
		$infos_cookie = array('tentative_identification' => false, 'expire' => 0);
221
		$infos_cookie = array('tentative_identification' => false, 'expire' => 0);
224
		$this->setInfosCookie($infos_cookie);
222
		$this->setInfosCookie($infos_cookie);
225
		// On demande à l'annuaire si l'utilisateur est bien valide
223
		// On demande à l'annuaire si l'utilisateur est bien valide
226
		$annuaire_url = $this->wiki->config['sso_url'].'connexion?login='.$login.'&password='.$pass;
224
		$annuaire_url = $this->wiki->config['sso_url'].'connexion?login='.$login.'&password='.$pass;
227
		$url = $annuaire_url.'&redirect_url='.urlencode($url_redirect);
225
		$url = $annuaire_url.'&redirect_url='.urlencode($url_redirect);
228
 
226
 
229
		header('Location: '.$url);
227
		header('Location: '.$url);
230
		exit;
228
		exit;
231
	}
229
	}
232
 
230
 
233
	function deconnecterUtilisateur($url_redirect = null) {
231
	function deconnecterUtilisateur($url_redirect = null) {
234
		$url_redirect = ($url_redirect == null) ? $this->wiki->config['base_url'].'PagePrincipale' : $url_redirect;
232
		$url_redirect = ($url_redirect == null) ? $this->wiki->config['base_url'].'PagePrincipale' : $url_redirect;
235
		// Suppression d'un eventuel jeton contenu dans l'url
233
		// Suppression d'un eventuel jeton contenu dans l'url
236
		$url_redirect = $this->supprimerUrlVar($url_redirect, 'Authorization');
234
		$url_redirect = $this->supprimerUrlVar($url_redirect, 'Authorization');
237
		
235
		
238
		$infos_cookie = array('tentative_identification' => false, 'expire' => 0);
236
		$infos_cookie = array('tentative_identification' => false, 'expire' => 0);
239
 		$this->setInfosCookie($infos_cookie);
237
 		$this->setInfosCookie($infos_cookie);
240
		// On demande à l'annuaire si l'utilisateur est bien valide
238
		// On demande à l'annuaire si l'utilisateur est bien valide
241
		$annuaire_url = $this->wiki->config['sso_url'].'deconnexion';
239
		$annuaire_url = $this->wiki->config['sso_url'].'deconnexion';
242
		$url = $annuaire_url.'?redirect_url='.urlencode($url_redirect);
240
		$url = $annuaire_url.'?redirect_url='.urlencode($url_redirect);
243
		header('Location: '.$url);
241
		header('Location: '.$url);
244
		exit;
242
		exit;
245
	}
243
	}
246
}
244
}
247
?>
245
?>