http headers - redireccionar - ¿Es posible enviar un 401 redireccionamiento AND no autorizado(con una ubicación)?
redireccionar una pagina web a otro dominio (8)
Me gustaría enviar un 401 Unauthorized
y redirigir al cliente a alguna parte. Sin embargo:
si lo hago así:
header(''HTTP/1.1 401 Unauthorized'');
header(''Location: /'');
el servidor envía un 302 Found
with Location
, por lo que no es un 401 Unauthorized
.
Si lo hago así:
header(''Location: /'');
header(''HTTP/1.1 401 Unauthorized'');
el navegador recibe tanto un 401 Unauthorized
como una Location
, pero no lo redirecciona.
(IE 9 y Chrome 16 se comportan igual, así que supongo que es correcto)
Tal vez estoy haciendo mal uso de HTTP? Me gustaría que la interfaz de mi aplicación sea exactamente la misma para todos los clientes: navegador de texto, navegador moderno, llamadas API, etc. El texto de respuesta 401 + le diría a un usuario API qué es qué. La redirección es útil para un navegador.
¿Hay una (buena) manera?
¿Podría ser esto lo que necesitas? Me crucé con esto antes con la misma pregunta.
if(user_has_no_rights())
{
header(''HTTP/1.1 401 Unauthorized'');
echo $this->requestAction(''anothercontroller/action'',
array(''return''));
$this->autoRender = false;
$this->layout = '''';
die();
}
Además de las buenas respuestas de Kolink y David (+1), señalaría que está intentando cambiar la semántica del protocolo HTTP devolviendo un 401 Y diciéndole al navegador que redirija. No es así como debe funcionar el protocolo HTTP, y si encuentra una forma de obtener ese resultado, los clientes HTTP encontrarán que el comportamiento de su servicio no es estándar.
O envía un 401 y permite que el navegador lo maneje, o maneja la situación de manera diferente (por ejemplo, como sugirió un comentarista, redirija a una página de inicio de sesión o tal vez a una página explicando por qué el usuario no tuvo acceso).
Aquí hay una manera limpia:
En la página 401, puede elegir la "vista" para enviar en función del encabezado "aceptar" en la solicitud.
Si el accept es application/json
, puede incluir el cuerpo:
{"status":401;"message":"Authentication required"}
Si el "aceptar" es text/html
, puede incluir el cuerpo:
<form action="/signin" method="post">
<!-- bla bla -->
<input type="hidden" name="redirect" value="[URL ENCODE REQUEST URI]">
</form>
Luego se encuentra con la misma pregunta ... ¿emite un 200 OK
o un 302 Found
en un inicio de sesión exitoso? (¿Ves lo que hice ahí? )
Si puede manejar la autenticación en cualquier página, puede hacer que la acción del formulario sea la misma URL de la página, pero esté atento a XSS si está colocando el request_uri proporcionado por el usuario en el atributo de acción de formulario.
Llegaré muy tarde aquí, pero pensé que agregaría mis dos centavos. Según tengo entendido, el deseo es indicar que el usuario no tiene la autorización correcta y solicitarles que inicien sesión. Rudie comprensiblemente desearía devolver 401 no autorizado (porque el usuario necesita autorizar mediante algún mecanismo, por ejemplo, el registro). in), y también reenviarlos a la página de inicio de sesión, pero esto no es muy fácil de lograr y la mayoría de las bibliotecas no lo admiten de fábrica. Una solución es mostrar la página de inicio de sesión en el cuerpo de la respuesta 401, como se sugirió en otra respuesta. Sin embargo, permítanme echar un vistazo a esto desde la perspectiva de las mejores prácticas establecidas.
Caso de prueba 1: Facebook
Navegar a una página de Facebook protegida (mi perfil de usuario) mientras está desconectado da como resultado una respuesta 404 No encontrada. Facebook ofrece una página de propósito general "esta página no está disponible", que también incluye un formulario de inicio de sesión. Interesante. Aún más interesante: cuando navego a la página de "eventos", recibo una respuesta 302 que reenvía a una página de inicio de sesión (que devuelve una respuesta de 200). Así que supongo que su idea es devolver 302 para las páginas que sabemos que existen, pero sirven 404 para las páginas que pueden existir o no (por ejemplo, para proteger la privacidad de un usuario).
Caso de prueba 2: bandeja de entrada de Google
Navegar a mi bandeja de entrada cuando estoy desconectado devuelve 302 y me envía a una página de inicio de sesión, similar a Facebook. No pude averiguar cómo hacer que mi perfil de Google+ sea privado, por lo que no hay datos de prueba allí ...
Caso de prueba 3: Amazon.com
Navegando hasta el historial de mi pedido cuando estoy desconectado, devuelve 302 y me envía a una página de inicio de sesión como antes. Amazon no tiene concepto de una página de "perfil", así que tampoco puedo probarla aquí.
Para resumir los casos de prueba aquí, parece una mejor práctica devolver un 302 Encontrado y reenviar a una página de inicio de sesión si el usuario necesita iniciar sesión (aunque yo diría que 303 Ver Otro es realmente más apropiado). Esto es, por supuesto, solo en el caso en el que un usuario humano real necesita ingresar un nombre de usuario y contraseña en formato html. Para otros tipos de autenticación (por ejemplo, básica, clave de API, etc.), 401 no autorizado es obviamente la respuesta adecuada. En este caso, no es necesario reenviar a una página de inicio de sesión.
Los navegadores web no son clientes REST. Se adhieren al envío del estado 200 con un encabezado de Ubicación y sin contenido corporal. Los redireccionamientos 30x son para páginas que se han movido. Ningún otro código de estado / encabezado de ubicación debe redirigirse en un navegador web.
Alternativamente, su servidor web puede tener páginas de error configurables. Puede agregar javascript a la página de error para redirigir.
Por definición (ver RFC 2616 ), el código de respuesta HTTP 302
es el código de redirección. Sin él, el encabezado de ubicación puede ser ignorado.
Sin embargo, puede enviar una respuesta HTTP 401
y seguir mostrando la salida. En lugar de redirigir al usuario a una página de error, simplemente puede escribir el contenido que desea enviar en el cuerpo HTTP en la misma solicitud.
Puede enviar 401 y luego en el cuerpo de respuesta puede enviar window.location = ''domain.com''. Sin embargo, el usuario será redirigido inmediatamente sin saber que ocurrió 401.
3xx
significa redirigir
4xx
significa que el navegador hizo algo mal.
Hay una razón por la cual los códigos se dividen tal como están: no se mezclan;)