Est-il possible d'envoyer un 401 non autorisé et rediriger (avec un emplacement)?

Je voudrais envoyer un 401 Unauthorized ET rediriger le client quelque part. Cependant:

Si je le fais comme ceci:

header('HTTP/1.1 401 Unauthorized');
header('Location: /');

, Le serveur envoie un 302 Found avec Location, donc pas un 401 Unauthorized.

Si je le fais comme ceci:

header('Location: /');
header('HTTP/1.1 401 Unauthorized');

Le navigateur reçoit à la fois un 401 Unauthorized et un Location, mais ne redirige pas.

(IE 9 et Chrome 16 se comportent de la même manière, donc je suppose que c'est correct)

Peut-être que J'utilise mal HTTP? Je voudrais que mon interface d'application soit exactement la même pour tous les clients: navigateur de texte, navigateur moderne, appels API, etc. Le texte de réponse 401 + indiquerait à un utilisateur D'API ce qui est quoi. La redirection est utile pour un navigateur.

Y a-t-il un (bon) moyen?

34
demandé sur Rudie 2012-01-08 09:24:48

8 réponses

Par définition (voir RFC 2616), le HTTP 302 code de réponse est le code de redirection. Sans cela, l'en-tête d'emplacement peut être ignoré.

Cependant, vous pouvez envoyer une réponse HTTP 401 et toujours afficher la sortie. Au lieu de rediriger l'utilisateur vers une page d'erreur, vous pouvez simplement écrire le contenu que vous souhaitez envoyer dans le corps HTTP dans la même requête.

26
répondu David Chan 2018-09-06 13:59:41

Je viens très tard ici, mais je pensais ajouter mes deux cents. Si je comprends bien, le désir est d'indiquer que l'utilisateur n'a pas l'autorisation correcte et de l'inviter à se connecter. Rudie naturellement voudrait retourner 401 non autorisé (parce que l'utilisateur doit autoriser par un mécanisme, par exemple. connectez-vous), et aussi les transférer à la page de connexion - mais ce n'est pas très facile à accomplir et n'est pas pris en charge par la plupart des bibliothèques. Une solution consiste à afficher la page de connexion dans le corps de la réponse 401, comme cela a été suggéré dans une autre réponse. Cependant, permettez-moi de jeter un oeil à cela du point de vue de la pratique établie/meilleure.

Cas de Test 1: Facebook

La navigation vers une page Facebook protégée (mon profil utilisateur) lors de la déconnexion entraîne une réponse 404 Not Found. Facebook sert un usage général "cette page n'est pas disponible" page, qui comprend également un formulaire de connexion. Intéressant. Encore plus intéressant: quand je navigue vers la page "événements", on me sert une réponse 302 qui transmet à une page de connexion (qui renvoie une réponse 200). Donc, je suppose que leur idée est de retourner 302 pour les pages que nous savons existent, mais servir 404 pour les pages qui peuvent ou peuvent ne pas exister (par exemple. pour protéger votre vie privée).

Cas de Test 2: boîte de réception Google

La navigation vers ma boîte de réception lorsque je suis déconnecté renvoie 302 et me redirige vers une page de connexion, similaire à Facebook. Je n'étais pas capable de comprendre comment faire mon Google+ profil privé, donc pas de données de test là...

Cas D'essai 3: Amazon.com

La navigation vers Mon historique de commandes lorsque je suis déconnecté renvoie 302 et me redirige vers une page de connexion comme précédemment. Amazon n'a pas le concept d'une page" Profil", donc je ne peux pas tester cela ici non plus.

Pour résumer les cas de test ici, il semble être la meilleure pratique de renvoyer un 302 trouvé et de le transmettre à une page de connexion si l'Utilisateur a besoin de se connecter (bien que je dirais 303 voir autre est en fait plus approprié). Ceci est bien sûr juste dans le cas où un utilisateur humain réel doit entrer un nom d'utilisateur et un mot de passe dans un formulaire html. Pour d'autres types d'authentification (par exemple. de base, clé api, etc.), 401 non autorisé est évidemment la réponse appropriée. Dans ce cas, il n'est pas nécessaire pour avancer vers une page de connexion.

10
répondu tytk 2017-01-24 19:50:56

3xx signifie rediriger
4xx signifie que le navigateur a fait quelque chose de mal.

Il y a une raison pour laquelle les codes sont divisés comme ils sont - ils ne se mélangent pas;)

8
répondu Niet the Dark Absol 2012-01-08 05:30:10

En plus des bonnes réponses de Kolink et David (+1), Je voudrais souligner que vous essayez de changer la sémantique du protocole HTTP en retournant un 401 et en disant au navigateur de rediriger. Ce n'est pas ainsi que le protocole HTTP est destiné à fonctionner, et si vous trouvez un moyen d'obtenir ce résultat, les clients HTTP trouveront que le comportement de votre service est non standard.

Soit vous envoyez un 401 et permettez au navigateur de le gérer, soit vous gérez la situation différemment (par exemple, comme l'a suggéré un commentateur, rediriger vers une page de connexion ou peut-être vers une page expliquant pourquoi l'utilisateur n'avait pas accès).

4
répondu Eric J. 2012-01-08 05:46:10

Voici une façon propre:

Sur la page 401, vous pouvez choisir la " vue "à envoyer en fonction de l'en-tête" accepter " dans la requête.

Si l'accepter, c'est application/json, alors vous pouvez inclure le corps:

{"status":401;"message":"Authentication required"}

Si la "accepter" est text/html, alors vous pouvez inclure le corps:

<form action="/signin" method="post">
    <!-- bla bla -->
    <input type="hidden" name="redirect" value="[URL ENCODE REQUEST URI]">
</form>

Ensuite, vous rencontrez la même question... donnez-vous un 200 OK ou 302 Found sur une connexion réussie? (voir ce que j'ai fait là? )

Si vous pouvez gérer l'authentification sur n'importe quelle page, vous pouvez juste avoir la forme action soit la même URL de page, mais surveillez XSS Si vous placez le request_uri fourni par l'utilisateur dans l'attribut action de formulaire.

2
répondu Frank Forte 2016-03-10 20:24:25

Vous pouvez envoyer 401, puis dans le corps de réponse, vous pouvez envoyer window. location='domain.com'. cependant, l'Utilisateur sera immédiatement redirigé sans savoir que 401 a eu lieu.

1
répondu rkosegi 2012-01-08 06:00:50

Les navigateurs Web ne sont pas des clients REST. Respectez le statut d'envoi 200 avec un en-tête D'emplacement et aucun contenu de corps. Les redirections 30x sont pour les pages qui ont été déplacées. Aucun autre en-tête de code/emplacement d'état ne devrait être redirigé dans un navigateur web.

Sinon, votre serveur web peut avoir des pages d'erreur configurables. Vous pouvez ajouter javascript à la page d'erreur à rediriger.

1
répondu Jeff Harris 2017-12-23 00:06:58

Cela Pourrait-il être ce dont vous avez besoin? Je suis tombé sur cela moi-même avant avec la même question.

if(user_has_no_rights()) 
{ 
   header('HTTP/1.1 401 Unauthorized');
   echo $this->requestAction('anothercontroller/action', 
array('return')); 

   $this->autoRender = false;
   $this->layout = ''; 
   die(); 
}
0
répondu Josh 2012-01-08 05:37:08