Page 404 personnalisée

Nouveau WRInaute
Bonjour,

Quand un visiteur entre un lien incorrect comme monsite.com/indexx.php au lieu de monsite.com/index.php, il arrive sur une page 404 qu'il est possible de configurer.

Mais comment faire, pour créer aussi une page erreur 404 quand le paramètre d'un lien est incorrect, par exemple si monsite.com/page.php?page=la_page n'existe pas mais page.php existe.

Car, cette technique permettrait d'éviter aux hackers de mettre des paramètres "bidons" (injections SQL...) pour hacker le site (enfin je pense, contredisez moi si c'est le cas).

Merci d'avance,
Thomas.
 
WRInaute passionné
il faut le faire en php :
Code:
//if (...) { //rien dans la table pour $_GET['page']
		header('Status: 404 Not Found', true, 404);
		include(dirname(__FILE__) . '/erreur404.php');  // la page 404 personnalisée
		exit;
}
 
WRInaute accro
je complete le IF de Forty :)

Code:
 <?php 
        $q = mysql_query("SELECT * FROM table WHERE la_page='$la_page' ");
    if (($r = mysql_fetch_array($q)) === false) {
        header('Status: 301 Moved Permanently', false, 301);
        header('Location: ' . url_erreur());
        exit;
    }
?>
 
WRInaute passionné
Ouais enfin bon, le faire par SQL est un peu se compliquer la vie pour rien
Code:
if (isset($_GET['page'])) {
$page = trim($_GET['page']);
} else {
$page = 'defaut';
switch ($page) {
case 'un': require_once('ce_que_tu_veux_un.php');
break;
case 'deux': require_once('ce_que_tu_veux_deux.php');
break;
case 'defaut': require_once('ta_page_par_defaut');
break;
default: 
require_once('ton_template_404.php');
}

Pas checké la structure mais c'est la technique la plus simple.
Et renvoyer il faut renvoyer un 4** pas un 3** sinon ce n'est pas un code erreur.
 
Nouveau WRInaute
forty a dit:
il faut le faire en php :
Code:
//if (...) { //rien dans la table pour $_GET['page']
		header('Status: 404 Not Found', true, 404);
		include(dirname(__FILE__) . '/erreur404.php');  // la page 404 personnalisée
		exit;
}

KOogar a dit:
je complete le IF de Forty :)

Code:
 <?php 
        $q = mysql_query("SELECT * FROM table WHERE la_page='$la_page' ");
    if (($r = mysql_fetch_array($q)) === false) {
        header('Status: 301 Moved Permanently', false, 301);
        header('Location: ' . url_erreur());
        exit;
    }
?>

Merci pour votre aide.


Quelques questions :
Il y a vraiment 3 "=" (===) ou tu en as mis un de trop ? :)
Le statut faudrait le passer en 404 non ?
Je met ça juste après mon </head> ?

Julia41 a dit:
Ouais enfin bon, le faire par SQL est un peu se compliquer la vie pour rien
Code:
if (isset($_GET['page'])) {
$page = trim($_GET['page']);
} else {
$page = 'defaut';
switch ($page) {
case 'un': require_once('ce_que_tu_veux_un.php');
break;
case 'deux': require_once('ce_que_tu_veux_deux.php');
break;
case 'defaut': require_once('ta_page_par_defaut');
break;
default: 
require_once('ton_template_404.php');
}

Pas checké la structure mais c'est la technique la plus simple.
Et renvoyer il faut renvoyer un 4** pas un 3** sinon ce n'est pas un code erreur.

Je n'ai pas trop compris ce que tu veux faire ici, comment sais tu que la valeur du paramètre n'existe pas avec ce code ?
 
WRInaute accro
les 3 signes d'égalité sont correcte. La fonction retourne des entiers et si la valeur n'est pas trouvé elle retourne un booléen

$a == $b Egal TRUE si $a est égal à $b
$a === $b Identique TRUE si $a est égal à $b et qu'ils sont de même type

j'ai mixer les 2 codes

Code:
<?php
     $q = mysql_query(" SELECT *
                        FROM table
                        WHERE la_page='".$_GET['la_page']."'
                       ");

     if (($r = mysql_fetch_array($q)) === false ) {
      header('Status: 404 Not Found', true, 404);
      include(dirname(__FILE__) . '/erreur404.php'); // la page 404 personnalisée
      exit;
     }

?>
 
WRInaute accro
KOogar a dit:
les 3 signes d'égalité sont correcte car la fonction retourne des entiers et si la valeur est trouvé elle retourne un booléen

$a == $b Egal TRUE si $a est égal à $b
$a === $b Identique TRUE si $a est égal à $b et qu'ils sont de même type

HS : merci, j'aurais appris quelque chose aujourd'hui !
 
Nouveau WRInaute
@Koogar : J'ai ajouté entre mes balises <head> le code suivant :

Code:
<?php
     $q = mysql_query(" SELECT *
                        FROM ma_table
                        WHERE lien='".$_GET['lien']."'
                       ");

     if (($r = mysql_fetch_array($q)) === false ) {
      header('Status: 404 Not Found', true, 404);
      include(dirname(__FILE__) . '/page404.php'); // la page 404 personnalisée
      exit;
     }

?>

Si je passe un mauvais paramètre, j'ai l'erreur suivante qui boucle à l'infinie :
Code:
Warning: Cannot modify header information - headers already sent by (output started at C:\Program Files\EasyPHP5.3.0\www\site\entete.php:4) in C:\Program Files\EasyPHP5.3.0\www\site\entete.php on line 112
 
WRInaute passionné
l'envoi d'un entête http avec la fonction header doit être faite avant tout envoi de texte (y compris avant des espaces). Il faut donc le mettre avant ton code html.
 
Nouveau WRInaute
Merci j'ai mis ça à la toute première ligne. Cependant j'ai un autre problème (ils s'enchainent définitivement) :

Code:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 261900 bytes) in C:\Program Files\EasyPHP5.3.0\www\site\entete.php on line 1

Ça me parait bizarre qu'il y ait un dépassement de mémoire...
 
WRInaute passionné
tu as peut-être un include d'un script qui contient lui même un include de entete.php

il faut peut-être que tu déplaces ton traitement au début de page.php
 
Nouveau WRInaute
Bah c'est au début. Avant je fais un include pour la connexion à la base mysql et je fais une requête pour récupérer les infos de la page. Je ne peux pas mettre ce code plus haut !
 
Nouveau WRInaute
Voila ce que j'ai :

Code:
$variable = $_GET['variable'];

$q = mysql_query(" SELECT *
                        FROM table
                        WHERE champs = '$variable'
                       ");

 if (($r = mysql_fetch_array($q)) === false ) {
	header('Status: 404 Not Found', true, 404);
	header("Location: ./page404.php");
    exit;
}

Et je l'ai mis sur chaque page tout en haut (juste après la connexion à la BDD)
 
WRInaute passionné
Salut,

J'ai crée ce code ci-dessous pour vérifier si une page existe bien, si elle n'existe pas je renvoie vers ma page 404 personalisée (erreur.php) :

Code:
$result_url = get_requete("SELECT * FROM table_url WHERE url LIKE '%".$url_lien."%'");
$nb_url = mysql_num_rows($result_url);
if($nb_url==0){
header('Status: 404 Not Found', true, 404);
header("Location: ./erreur.php?404");
 exit;
}

Lorsque je rentre dans mon browser une mauvaise url, cela me renvoie bien vers pas page 404 personalisée (erreur.php?404) mais lorsque je vérifie l'entête HHTP de cette mauvaise url j'ai cela :

Code:
HTTP/1.1 302 Found
Date: Sun, 07 Sep 2014 08:28:11 GMT
Server: Apache/2.2.20 (Unix) mod_ssl/2.2.20 OpenSSL/0.9.8o
Location: http://www.mon-site.com/erreur.php?404
Content-Type: text/html; charset=iso-8859-1

HTTP/1.1 404 Not Found
Date: Sun, 07 Sep 2014 08:28:11 GMT
Server: Apache/2.2.20 (Unix) mod_ssl/2.2.20 OpenSSL/0.9.8o
X-Powered-By: PHP/5.2.13-pl1-gentoo
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=3c9f81d90834f457a17fda0296cbf9e1; path=/
Vary: User-Agent
Content-Type: text/html

Pourquoi j'ai d'abord une entête HTTP/1.1 302 Found et pas directement une entête HTTP/1.1 404 Not Found ?

Ca me fait plein d'erreur Soft 404 dans GWT ?

Merci pour vos réponses.
 
WRInaute passionné
c'est toi qui indique une redirection avec :
Code:
header("Location: ./erreur.php?404");

Il faut faire un include à la place.
 
WRInaute passionné
Merci pour vos réponses.

forty a dit:
c'est toi qui indique une redirection avec :
Code:
header("Location: ./erreur.php?404");

Il faut faire un include à la place.

Je ne vois pas ce que tu veux dire :? quel serait le bon code ?
 
WRInaute passionné
Il faut remplacer par :
Code:
include('./erreur.php');
Tu peux aussi alimenter avant $_GET['404'] si tu l'utilise dans erreur.php.
 
WRInaute passionné
forty a dit:
Il faut remplacer par :
Code:
include('./erreur.php');
Tu peux aussi alimenter avant $_GET['404'] si tu l'utilise dans erreur.php.

Oui j'utilise le '404' dans mon fichier erreur.php et je récupère le code de l'en-tête HTTP de cette manière :

Code:
if($_SERVER['QUERY_STRING']=='401'){header("HTTP/1.1 401 Unauthorized");}
if($_SERVER['QUERY_STRING']=='403'){header("HTTP/1.1 403 Forbidden");}
if($_SERVER['QUERY_STRING']=='404'){header("HTTP/1.1 404 Not Found");}
if($_SERVER['QUERY_STRING']=='500'){header("HTTP/1.1 500 Internal Server Error");}

J'ai essayé ce code ci-dessous :

Code:
$result_url = get_requete("SELECT * FROM table_url WHERE url LIKE '%".$url_lien."%'");
$nb_url = mysql_num_rows($result_url);
if($nb_url==0){
header('HTTP/1.1: 404 Not Found', true, 404);
include('Location: ./erreur.php?404');
exit;
}

mais j'ai ce warning qui s'affiche :

Code:
Warning: include(C:/wamp/www/mon-site.com/erreur.php?404) [function.include]: failed to open stream: No error in C:\wamp\www\mon-site.com\index.php on line 29

Est-ce que ce code est bon :

Code:
$result_url = get_requete("SELECT * FROM table_url WHERE url LIKE '%".$url_lien."%'");
$nb_url = mysql_num_rows($result_url);
if($nb_url==0){
header('HTTP/1.1: 404 Not Found', true, 404);
include('Location: ./erreur.php?404');
exit;
}
 
WRInaute passionné
Tu n'as pas besoin du paramètre "404" si tu as le header "404".

Si tu remplaces l'include que tu as mis par celui que j'ai indiqué ca doit marcher.
 
WRInaute accro
Code:
$result_url = get_requete("SELECT * FROM table_url WHERE url LIKE '%".$url_lien."%'");
$nb_url = mysql_num_rows($result_url);
if($nb_url == 0){
header('HTTP/1.1: 404 Not Found', true, 404);
include('./erreur.php?404');
}
 
WRInaute passionné
HawkEye a dit:
Code:
$result_url = get_requete("SELECT * FROM table_url WHERE url LIKE '%".$url_lien."%'");
$nb_url = mysql_num_rows($result_url);
if($nb_url == 0){
header('HTTP/1.1: 404 Not Found', true, 404);
include('./erreur.php?404');
}

Ce code me renvoie un warning :

Code:
Warning: include(/home/www/erreur.php?404) [function.include]: failed to open stream: No such file or directory in /home/www/index.php on line 24

J'ai essayé en ajoutant le path du fichier erreur.php mais ça affiche le même warning.

Si j'essaie ce code :

Code:
$result_url = get_requete("SELECT * FROM table_url WHERE url LIKE '%".$url_lien."%'");
$nb_url = mysql_num_rows($result_url);
if($nb_url==0){
header('HTTP/1.1 404 Not Found', true, 404);
include('Location: ./erreur.php);
exit;
}

Ca me renvoie bien un code 404 si j'analyse avec un outil d'analyseur d'en-tête le code retour de l'en-tête mais ma page erreur.php (404) ne s'affiche pas pour ce code d'erreur, comment récupérer le code '404' dans ma page erreur.php ?
 
WRInaute passionné
Tu ne peux pas avoir de paramètres dans un include.

tu peux ajouter avant l'include cette ligne :
Code:
$_GET['404']='';
et remplacer les tests par un truc du style :
Code:
if(isset($_GET['401'])){header("HTTP/1.1 401 Unauthorized");}
...
 
WRInaute passionné
Ca fonctionne :)

Ma page erreur.php affiche les erreurs 401, 403, 404 et 500, comment faire pour détecter le code de statut de la page et afficher dans ma page erreur.php le bon message d'erreur.

Si j'ai une erreur 403 (Forbidden) ou je vais faire rajouter le $_GET['403']=''; dans mon code php ?

Ne peut-on pas détecter dans ma page erreur.php le code statut de l'en-tête HTTP de la page demandée et afficher le bon message d'erreur ?
 
WRInaute passionné
tu as deux cas :
soit tu définis une page 40X personnalisée dans le .htaccess et dans ce cas tu peux appeler erreur.php avec un paramètre
soit tu changes le code retour en php comme dans le cas que tu cites et là tu définis le paramètre GET comme indiqué suivi d'un include (car l'instruction include ne permet pas d'appeler avec un paramètre GET).

Si tu veux en php une erreur 403 tu mets :
Code:
 if (<ta condition>) {
    header('HTTP/1.1 403 Forbidden', true, 403);
    $_GET['403']='';
    include('Location: ./erreur.php);
}
Il ne faut pas oublier d'adapter erreur.php pour ne plus tester $_SERVER['QUERY_STRING'] qui n'est pas bon dans ce dernier cas mais de tester la présence de tes variables $_GET['403'], $_GET['404'], ... avec isset().
 
WRInaute passionné
Entendu forty.

Par contre je ne vois pas quelle condition je vais mettre dans les if (<ta condition>) { } pour les différents codes d'erreurs (401, 403 et 500) ?

Pour rappel :
Erreur 401 = Unauthorized
Erreur 403 = Forbidden
Erreur 404 = Not Found
Erreur 500 = Internal Server Error

Comment je peux savoir quelle(s) condition(s) if (<ta condition>) { } se traduira par une erreur 401, 403 ou 500 ?
 
WRInaute passionné
c'est à toi de voir ;)

Je retourne par exemple une erreur 403 en php quand une IP charge un trop grand nombre de pages en 1 minute ou quand elle essaye d'accéder à des pages inexistante (du style un répertoire /wordpress alors que je n'ai pas wordpress). Ca permet de bloquer les hackers et les robots qui utilisent trop de ressources. Si tu ne veux pas gérer ce genre de cas particulier tu peux laisser le paramétrage dans le .htaccess et ne rien faire en php (en dehors des erreurs 404).
 
WRInaute passionné
Merci pour ton aide forty j'apprécie grandement :)

J'ai configuré correctement ma page erreur.php pour les erreurs 404 avec le $_GET['404']=''; et if(isset($_GET['404'])){header("HTTP/1.1 404 Not found");}, si je laisse tel quel dans mon fichier erreur.php pour les autres erreurs (401, 403 et 500) est-ce que c'est pas trop grave ?

Quelle serait un exemple d'url qui ferait une erreur 500 ?

D'autre part, si je rentre dans mon browser une url du type http://www.mon-site.com/?=bachibouzouke il ne renvoie pas d'erreur 404, par contre si j'enlève le ? dans l'url j'ai bien une erreur 404 :? comment parer à ce type d'url qui ne retournerai pas d'erreur 404 ?
 
WRInaute passionné
500 c'est une erreur du serveur donc a priori ponctuel comme pour une surcharge. Une erreur de syntaxe dans le .htaccess retourne une erreur 500 il me semble.

Pour gérer ton cas de paramètre tu dois le traiter en php. Tu peux faire deux contrôles : un premier qui vérifie que l'URL appelée correspond bien à celle que tu attends et rediriger vers la bonne si c'est différent (comme ça un contenu = une URL et pas de duplicate content). C'est d'autant plus important en cas de réécriture car deux URL différentes peuvent afficher le même contenu. Un deuxième contrôle consisterait à vérifier que chaque paramètre GET ou POST est bien autorisé selon la page concernée. Si c'est, comme ton exemple, un paramètre GET en trop, tu rediriges vers la bonne page et s'il s'agit de paramètres POST tu peux renvoyer une erreur 403 car il y a de fortes chances que ce soit un hacker qui cherche une faille. Et si tu ne veux pas t'emmerder tu ne fait rien et tu ajoutes juste une balise canonical contenant l'adresse de la page.
 
Discussions similaires
Haut