[RESOLU] une alternative à HTTP_REFERER

Invité
Invité n'ayant pas de compte PHPfrance

12 juil. 2007, 12:39

Salut ^^

je developpe une application en html/php et j'utilise HTTP_REFERER, mais suite à un problème j'ai fait des recherches et je suis tombé sur ce sujetzigz4g explique que l'utilisateur peut bloquer HTTP_REFERER.


Donc si quelqu'un sait comment récupérer l'adresse de la page précédente/parente ça m'aiderait bien :D


Merci de votre aide :wink:

Petit nouveau ! | 8 Messages

12 juil. 2007, 12:40

oups j'étais pas connecté :oops:
Idéalement nous sommes ce que nous pensons. Dans la réalité, nous sommes ce que nous accomplissons.
Ayrton Senna

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9783 Messages

12 juil. 2007, 12:53

Bonjour,

Si tu veux avoir le Referer qui est une page de ton site alors oui tu peux contourner HTTP_REFERER en utilisant les sessions.
En revanche, si tu veux avoir le Referer alors que ton visiteur arrive d'un autre site que le tien, alors tu ne peux rien faire de +...
Quand tout le reste a échoué, lisez le mode d'emploi...

Petit nouveau ! | 8 Messages

12 juil. 2007, 13:26

Si tu veux avoir le Referer qui est une page de ton site alors oui tu peux contourner HTTP_REFERER en utilisant les sessions.
En revanche, si tu veux avoir le Referer alors que ton visiteur arrive d'un autre site que le tien, alors tu ne peux rien faire de +...
Justement je le fait déjà avec un login (pour forcer l'utilisateur à s'identifier) mais c'est trop permissif.

Par exemple je navigue sur l'application avec FireFox, si j'ouvre un autre onglet je peux accéder à l'application. Pire l'utilisateur quitte l'application en cliquant sur un favori, il peut revenir à l'application sans avoir besoin de s'identifier, la session restant valide.


L'utilisation d'une variable de temps n'est pas suffisante, puisque certains pc sont utilisés par plusieurs utilisateurs et je veux être certain qu'ils se sont bien identifier à chaque fois. D'où l'utilisation du referer, si la session existe encore mais que le referer n'est pas bon alors je tue la session et l'utilisateur doit s'identifier.
Idéalement nous sommes ce que nous pensons. Dans la réalité, nous sommes ce que nous accomplissons.
Ayrton Senna

ViPHP
ViPHP | 1996 Messages

12 juil. 2007, 13:26

même en javascript ? (si disponible bien évidemment)
It is nice to be important but it is more important to be nice
http://www.aureuswebfactory.fr

Petit nouveau ! | 8 Messages

12 juil. 2007, 14:18

même en javascript ? (si disponible bien évidemment)
arf
je viens de trouver document.referrer

Mais j'ai mon problème (celui qui m'a fait arriver ici) reste d'actualité, j'explique:

l'utilisateur peut créer des rapports d'événement:
ces évenements dépendent d'un lieu, d'un matériel et d'un motif.
Selon le lieu les matériels sont différents, donc j'affiche en premier la liste des lieux, qui lors d'un changement recharge la page, puis la liste des matériels.

le code donne ça:

Code : Tout sélectionner

<? /************************************************* *** *** *** Page pour créer un événement *** *** *** *** Parent(s): identification.php3 via index.php3 *** *** *** *************************************************/ //include "lib/connect.php3"; include "lib/fonction.mysql.php3"; $connect = sql_connect(); echo "\n\n\nCr&eacute;ation d'&eacute;v&eacute;nement !!\n"; # le début du form et la liste des chapitres echo "<form name="" action="">"; # on va faire 2 choses: récuperer la liste des chapitres et créer la liste $cquery = "SELECT `idchap`, `chapitre` FROM `ev_chapitre` WHERE `id_cell` = {$_SESSION['eb_user']['cellule']} ORDER BY `chapitre`"; $crow = sql_select($cquery, $connect); if ($crow['res'] == "ok"){ echo" chap:<select name="chap" onchange="window.location='index.php3'+'?'+'page=creat_ev'+'&chap='+eval('this.options[this.selectedIndex].value')">"; echo affich_select($crow,"chap"); echo"\n </select>"; if (isset($_SESSION['eb_param']['chap'])){ #un chapitre a été sélectionné #on commence par afficher les sous-chapitres $scquery = "SELECT `idsouschap`, `sous_chap` FROM `ev_sous_chap` WHERE `id_chap` = {$_SESSION['eb_param']['chap']} ORDER BY `sous_chap`"; $scrow = sql_select($scquery, $connect); if ($scrow['res'] == "ok"){ echo" sous chap:<select name="sous_chap" >"; echo affich_select($scrow,"sous_chap"); echo"\n </select>"; } # on affiche ensuite les objets (aucune restriction) $oquery = "SELECT `idobjet`, `objet` FROM `ev_objet` ORDER BY `objet`"; $orow = sql_select($oquery, $connect); if ($orow['res'] == "ok"){ echo" objet:<select name="objet" >"; echo affich_select($orow,"objet"); echo"\n </select>"; } echo "\n</br><hr></br>"; }#fin de if (isset($_SESSION['eb_param']['chap'])) }#if ($crow['res'] == "ok") de chapitre echo "</form>\n\n\n"; sql_disconnect($connect); ?> <script> document.write(document.referrer); </script>
$_SESSION['eb_param']['chap'] est connu grâce à index qui suit

Code : Tout sélectionner

# on commence par récupérer les paramètres, au minimum il ya la page qu'on veut if (isset($_REQUEST['page'])){ $_SESSION['eb_param'] = array ( "nom_param" => "val_param"); while (list($clef,$val) = each($_REQUEST)){ $_SESSION['eb_param'][$clef] = $val; } header("Location: ".$GLOBALS["APPLI"]["URL"]); } # on vérifie déjà si on sait où aller et si la connexion est valide if (!isset($_SESSION['eb_param']['page']) || cboncirculez() == 0 ){ $_SESSION['eb_param']['page'] = "connex"; } # on apelle la fonction charger de l'affichage avec l'id de la page voulue, voir lib/config.php3 pour les correspondances va_page($_SESSION['eb_param']['page']);
header me transforme mon URL en http://127.0.0.1/application/ l'utilisateur ne voyant que cette adresse


Tout ça fonctionne sans problème sous FireFox, sous Opera mais pas sous IE. Lors du rechargement de la page (à cause du onchange="window.location=....") Ie me perd mon referrer.
Idéalement nous sommes ce que nous pensons. Dans la réalité, nous sommes ce que nous accomplissons.
Ayrton Senna

ViPHP
ViPHP | 5924 Messages

12 juil. 2007, 14:21

Le referer n'a aucune valeur réelle, il est envoyé par le navigateur, qui envoie ce qu'il veut. Et dans certains navigateurs (Opera par exemple), tu peux même modifier le referer que le navigateur va envoyer. Donc il ne faut jamais se fier au referer, si tu veux une information fiable, ce sont les sessions...

Petit nouveau ! | 8 Messages

12 juil. 2007, 14:38

Le referer n'a aucune valeur réelle, il est envoyé par le navigateur, qui envoie ce qu'il veut. Et dans certains navigateurs (Opera par exemple), tu peux même modifier le referer que le navigateur va envoyer. Donc il ne faut jamais se fier au referer, si tu veux une information fiable, ce sont les sessions...
c'est ce que je craignais :?

bon je vais chercher un moyen pour éviter que l'utilisateur puissent revenir sur l'application aprés avoir quitter l'application sans c'être delogué.
Idéalement nous sommes ce que nous pensons. Dans la réalité, nous sommes ce que nous accomplissons.
Ayrton Senna

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9783 Messages

12 juil. 2007, 15:19

bon je vais chercher un moyen pour éviter que l'utilisateur puissent revenir sur l'application aprés avoir quitter l'application sans c'être delogué.
Il suffit de faire expirer sa session au bout de X minutes d'inactivité...
Pour cela, à chaque appel d'une page, tu notes (en bdd par exemple) l'heure actuelle et si l'heure précédemment noté est > à X minutes alors tu le délogues (et le renvoie vers la page de login)
C'est le système utilisé par les banques et ça marche plutôt bien normalement ;)

Sinon, l'autre solution est de modifier l'ensemble de ton site pour que tout se passe sur une seule page HTML (c'est possible avec beaucoup d'ajax) et quand le visiteur quitte ton application (=quitte la page), il sera délogué. Attention, cette 2ème solution est très difficile à mettre en oeuvre surtout si tu as beaucoup de pages dans ton application...
Quand tout le reste a échoué, lisez le mode d'emploi...

Petit nouveau ! | 8 Messages

13 juil. 2007, 08:39

Sinon, l'autre solution est de modifier l'ensemble de ton site pour que tout se passe sur une seule page HTML (c'est possible avec beaucoup d'ajax) et quand le visiteur quitte ton application (=quitte la page), il sera délogué. Attention, cette 2ème solution est très difficile à mettre en oeuvre surtout si tu as beaucoup de pages dans ton application...
C'est ce que je fait en php, tout passe par la page index et c'est lui qui décide quelle page chargée. La page index utilise aussi header pour modifier l'URL

Je vais mettre un timer, qui sera largement suffisant c'est vrai, :twisted: MAIS pour la beauté du geste je vais quand même continuer à chercher. Je l'avais déjà fait sur un serveur TOMCAT (qui était alors très simple) mais en php c'est plus compliqué T_T


Mais hier j'ai eu une idée qui fonctionne à moitié pour l'instant, faut que je la perfectionne et ça sera bon. 8-)
Idéalement nous sommes ce que nous pensons. Dans la réalité, nous sommes ce que nous accomplissons.
Ayrton Senna

Petit nouveau ! | 8 Messages

15 juil. 2007, 17:47

C'est bon j'ai réussit, mon idée fonctionnait bien c'était ma procédure de test qui était mauvaise :roll:

J'explique tout si quelqu'un est intéréssé il pourra l'utiliser ^^

Alors lors de la navigation sur l'application l'utilisateur voit toujours une URL du type:
http://serveur/appli

dans l'historique c'est la même chose. Mais en pratique l'URL est http://server/index?page=accueil

Pour faire celà j'utilise la fonction php header(), je garde les GET/POST dans une variable de session. Je le fait ainsi:
if (isset($_REQUEST['page'])){	
	
	$_SESSION['eb_param'] = array ( "nom_param" => "val_param");
	while (list($clef,$val) = each($_REQUEST)){
		$_SESSION['eb_param'][$clef] = $val;
	}
	$_SESSION['eb_ctrl']['look_param'] = 0;
	
	header("Location: ".$GLOBALS["APPLI"]["URL"]);
}
La variable de session est un tableau qui pour nom de case contient le nom du paramètre et pour valeur celle du paramètre. Par exemple avec l'URL http://serveur/appli?page=acc&login=popo
mon tableau donne:
[eb_param][page]=acc
[eb_param][login]=popo


J'ai donc 2 cas à bloquer, le cas où l'utilisateur lance le site avec l'url normal (http://serveur/appli) mais qu'il ne c'est pas déconnecter (je dois donc le retourner à la page de connex) et s'il veut forcer l'affichage d'une page en mettant http://serveur/appli?page=apge_voulue


Voici index:
<?include ("lib/fonction.lib.php3");
$papier = vospapiers();	
	
# on commence par récupérer les paramètres, au minimum il ya la page qu'on veut
if (isset($_REQUEST['page'])){	
	
	$_SESSION['eb_param'] = array ( "nom_param" => "val_param");
	while (list($clef,$val) = each($_REQUEST)){
		$_SESSION['eb_param'][$clef] = $val;
	}
	
	header("Location: ".$GLOBALS["APPLI"]["URL"]);
}

# on vérifie déjà si on sait où aller et si la connexion est valide
if (!isset($_SESSION['eb_param']['page']) || cboncirculez() == 0 || $papier == 0 ){ 
	$_SESSION['eb_param']['page'] = "connex";
}


# on apelle la fonction charger de l'affichage avec l'id de la page voulue, voir lib/config.php3 pour les correspondances
va_page($_SESSION['eb_param']['page']);
?>

La fonction vital est vospapier() contenu dans fonction.lib.php3:
/*****************************************
** 		vospapiers()			**
**						**
**  paramètre: aucun				**
**  retour: validité de l'url			**
** 						**
**   Cette fonction vérifie si l'utilisateur	**
** a le droit d'accéder à l'application	**
** ou s'il force l'affichage d'une page	**
**						**
******************************************/
function vospapiers(){

	$valid = 1;
	# on vérifie déjà si les variables de contrôle existe
	if (isset($_SESSION['eb_ctrl'])){
		$_SESSION['eb_ctrl']['oki'] = "ok";
		if (!isset($_SESSION['eb_ctrl']['check'] ))
			$_SESSION['eb_ctrl']['check'] = 2;

		if (isset($_REQUEST['page'])){
			$_SESSION['eb_ctrl']['url'] = $_REQUEST['page'];
			$_SESSION['eb_ctrl']['check'] = 0;
		}
		else{
			$_SESSION['eb_ctrl']['url'] = "err";
		}

		if ($_SESSION['eb_ctrl']['check'] == 1 && $_SESSION['eb_ctrl']['url'] != $_SESSION['eb_param']['page']){
			$_SESSION['eb_ctrl']['oki'] = "pas check";
			$valid = 0;
		}

		if ($_SESSION['eb_ctrl']['check'] == 0 && $_SESSION['eb_ctrl']['url'] == "err")
			$_SESSION['eb_ctrl']['check'] = 1;
			
		
		
		
	

		if (isset ($_SESSION['eb_param']['hier']) && $_SESSION['eb_ctrl']['referer'] != $_SESSION['eb_param']['hier']){
			$_SESSION['eb_ctrl']['oki'] = "pas oki";
			$valid = 0;
		}
		
		if (isset($_REQUEST['page'])){
			$_SESSION['eb_ctrl']['referer'] = $_SESSION['eb_param']['page'];
		}
	/*	else if (!isset($_REQUEST['page']) && $_SESSION['look_param'] == 1)
			$_SESSION['eb_ctrl']['referer'] = "err";
		*/
		
		
	}#fin de if (isset($_SESSION['eb_ctrl']
	else{
		$_SESSION['eb_ctrl']['oki'] = "first";
		$_SESSION['eb_ctrl']['url'] = "connex";
		$_SESSION['eb_ctrl']['referer'] = "connex";
	}
	$_SESSION['valid'] = $valid;
	return $valid;

}# fin de function vospapiers()
Je vais faire 2 posts suplémantaires pour expliquer partie par partie :wink:
Idéalement nous sommes ce que nous pensons. Dans la réalité, nous sommes ce que nous accomplissons.
Ayrton Senna

Petit nouveau ! | 8 Messages

15 juil. 2007, 18:01

Alors je commence par le bloquage du retour sur le site sans s'être délogué, il faut donc forcer le retour au login:

C'est le début de la fonction vospapiers()
	$valid = 1;
	# on vérifie déjà si les variables de contrôle existe
	if (isset($_SESSION['eb_ctrl'])){
		$_SESSION['eb_ctrl']['oki'] = "ok";
		if (!isset($_SESSION['eb_ctrl']['check'] ))
			$_SESSION['eb_ctrl']['check'] = 2;
Là l'utilisateur vient d'arriver sur l'application, je fixe [check] à une valeur qui ne fait rien, c'est juste pour ne pas avoir à mettre isset() à chaque if.
		if (isset($_REQUEST['page'])){
			$_SESSION['eb_ctrl']['url'] = $_REQUEST['page'];
			$_SESSION['eb_ctrl']['check'] = 0;
		}
		else{
			$_SESSION['eb_ctrl']['url'] = "err";
		}
Si j'ai donc une url finissant avec ?page=page_voulue, je la garde en mémoire et je met [check] à 0, comme ça je ne ferais aucun test.
Le else répondra donc soit juste à aprés l'appel à header (donc [check] = 0).
		if ($_SESSION['eb_ctrl']['check'] == 1 && $_SESSION['eb_ctrl']['url'] != $_SESSION['eb_param']['page']){
			$_SESSION['eb_ctrl']['oki'] = "pas check";
			$valid = 0;
		}

		if ($_SESSION['eb_ctrl']['check'] == 0 && $_SESSION['eb_ctrl']['url'] == "err")
			$_SESSION['eb_ctrl']['check'] = 1;
Là j'ai les "vrais" tests, [check] me permet de savoir si je viens d'utiliser header (de index). Si je viens de faire un header alors [check] vaut 0 et [url] vaut "err". Donc je fixe [check] à 1.
Si l'utilisateur quite sans se déloguer et qu'il revient sur l'application (avec http://serveur/appli) alors j'ai:
[check] = 1
[url] = err
[eb_param][page] = la dernière page voulue
Dans ce cas là je retourne l'utilisateur à la page de connexion.


C'est grâce à [check] que je sais quand je dois tester, car dans la logique je dois tester la 2 fois aprés avoir eu un GET/POST, car la première fois c'est la fonction header de index.


ça a été le plus simple à trouver. Maintenant le cas où l'utilisateur veut forcer l'affichage avec une URL style:
http://serveur/appli?page=page_voulue
Idéalement nous sommes ce que nous pensons. Dans la réalité, nous sommes ce que nous accomplissons.
Ayrton Senna

Petit nouveau ! | 8 Messages

15 juil. 2007, 18:30

Pour bloquer l'accés direct à une page en fixant l'URL il faut que chaque lien du site se présente ainsi:

Code : Tout sélectionner

<a href=\"{$GLOBALS["APPLI"]["URL"]}index.php3?page=creat_ev&hier={$_SESSION['eb_param']['page']}\">Cr&eacute;er un &eacute;v&eacute;nement</a>
['eb_param']['page'] est la page voulue, donc la page en cours :idea:
ce qui donne:
http://serveur/appli/index.php3?page=creat_ev&hier=acc

Pour rappel dans index je garde tout les paramètres de l'URL dans une variable de session, un tableau qui dans notre cas vaut:
[eb_param][page]=creat_ev
[eb_param][hier]=acc


Lors de la première connexion, il ya un test, enfin le else d'un test, qui répond:
function vospapiers(){

	$valid = 1;
	# on vérifie déjà si les variables de contrôle existe
	if (isset($_SESSION['eb_ctrl'])){
#--------------
# l'emplacement de mes tests
#---------------
	}#fin de if (isset($_SESSION['eb_ctrl']
	else{
		$_SESSION['eb_ctrl']['oki'] = "first";
		$_SESSION['eb_ctrl']['url'] = "connex";
		$_SESSION['eb_ctrl']['referer'] = "connex";
	}
	$_SESSION['valid'] = $valid;
	return $valid;

}# fin de function vospapiers()
Lors de la première connexion je renseigne donc:
['eb_ctrl']['oki'] = "first" <--- cette variable ne sert que pour le debug ;)
['eb_ctrl']['url'] = "connex"
['eb_ctrl']['referer'] = "connex"



Maintenant je peux tester que l'utilisateur à bien cliquer sur un lien, pour info l'appel de vospapiers() est la toute première chose que index fait.

A la place prévu il faut rajouter:
		if (isset ($_SESSION['eb_param']['hier']) && $_SESSION['eb_ctrl']['referer'] != $_SESSION['eb_param']['hier']){
			$_SESSION['eb_ctrl']['oki'] = "pas oki";
			$valid = 0;
		}
		
		if (isset($_REQUEST['page'])){
			$_SESSION['eb_ctrl']['referer'] = $_SESSION['eb_param']['page'];
		}
Avant l'appel à header:
Au premier if:
[eb_param][hier] est égale à la deuxième page précédente et [eb_param][referer] aussi.
Au deuxième if:
[eb_param][hier] ne change pas mais [eb_param][referer] devient la page précédente.

vospapiers() se termine et index sauvegarde les paramètres, alors [eb_param][hier] vaut la page précédente et on appel header:
retour dans vospapiers() où
[eb_param][hier] et [eb_param][referer] sont égale à la page précédente.


La seul cas où l'utilisateur peut réussir à forcer l'affichage d'une page est de mettre la bonne valeur de [hier] dans l'URL, il doit mettre le nom utiliser pour la dernière page consultée.
Je pourrais crypter [hier] avec l'heure de connexion de l'utilisateur mais ça serait superflu, déjà que ce que j'ai fait c'était juste pour le chalenge de pas utiliser la variable REFERER (chalenge qui m'a fait perdre 2 jours XD), je vais pas abuser :lol: :lol:


Voilà si vous avez des questions n'hésitez pas :wink:


EDIT: un modo pourrait metttre [Résolu] ??? Comme j'écrit le premier post en invité je peux pas l'éditer :oops: ... :roll: ... merci :D
Idéalement nous sommes ce que nous pensons. Dans la réalité, nous sommes ce que nous accomplissons.
Ayrton Senna