¿Cuál es la diferencia entre una redirección 302 y una 307?

208

¿Cuál es la diferencia entre ay 302 FOUNDuna 307 TEMPORARY REDIRECTrespuesta HTTP?

La especificación W3 parece indicar que ambos se usan para redireccionamientos temporales, y ninguno se puede almacenar en caché a menos que la respuesta lo permita específicamente.

Zach Hirsch
fuente

Respuestas:

99

Las preocupaciones de diferencia de redirección POST, PUTy DELETElas solicitudes y cuáles son las expectativas del servidor son para el comportamiento del agente de usuario ( RFC 2616):

Nota: RFC 1945 y RFC 2068 especifican que el cliente no puede cambiar el método en la solicitud redirigida. Sin embargo, la mayoría de las implementaciones de agentes de usuario existentes tratan 302 como si fuera una respuesta 303, realizando un GET en el valor de campo Ubicación, independientemente del método de solicitud original. Los códigos de estado 303 y 307 se han agregado para los servidores que desean dejar claro claramente qué tipo de reacción se espera del cliente.

Además, lea el artículo de Wikipedia sobre los códigos de redireccionamiento 30x .

Franci Penov
fuente
Entonces, desde una perspectiva de analizador / agente / navegador, simplemente podemos tratar 302 y 307 como idénticos, ¿verdad? (¿Se puede usar exactamente el mismo código para manejar ambos casos sin más distinción?)
Pacerier el
No, puede tratar 302 y 303 como idénticos, pero 307 es diferente.
Quentin Skousen
@kkhugs, de ninguna manera, se requiere un navegador 1.0 para obtener get-302 de la misma manera que get-307 se realiza en los navegadores 1.1. Se requiere un navegador 1.0 para hacer post-302 de la misma manera que lo hace con 302, excepto que primero debe requerir una confirmación del usuario para continuar, y el método debe ser publicado.
Pacerier
Se requiere un navegador 1.1 para obtener get-302 de la misma manera que get-307.
Pacerier
161

El 307 surgió porque los agentes de usuario adoptaron un comportamiento de facto para tomar solicitudes POST que reciben una respuesta 302 y enviar una solicitud GET al encabezado de respuesta de Ubicación.

Ese es el comportamiento incorrecto : solo un 303 debería hacer que un POST se convierta en un GET. Los agentes de usuario deben (pero no) seguir con el método POST cuando solicitan la nueva URL si la solicitud POST original devolvió un 302.

307 se introdujo para permitir que los servidores aclaren al agente de usuario que el cliente no debe realizar un cambio de método al seguir el encabezado de respuesta de Ubicación.

Christopher Orr
fuente
3
¿Algún ejemplo de agentes de usuario que respondan incorrectamente? ¿Suele ser un porcentaje muy pequeño de visitantes?
goodguys_activate
66
@ makerofthings7 Todos los navegadores se manejan 302incorrectamente. Chrome 30, IE10. Se convirtió en la implementación incorrecta de facto ; eso no se puede cambiar porque muchos sitios web emiten por error el 302. De hecho, ASP.net MVC emite incorrectamente 302, dependiendo del hecho de que los navegadores lo manejan incorrectamente.
Ian Boyd el
1
@IanBoyd La única razón por la que los marcos hacen esto es porque 303también se introdujo 307en la especificación HTTP 1.1 y, por lo tanto, permite la compatibilidad con los agentes de usuario HTTP 1.0. Por supuesto, la verdadera pregunta es ¿deberíamos seguir manejando agentes de usuario HTTP 1.0 ahora?
ewanm89
1
@ ewanm89 Parece ser que el marco podría crear el método de respuesta con el nombre correcto (por ejemplo Response.RedirectSeeOther), y si el cliente no es 1.1 (por ejemplo ) GET /foo.html, GET /foo.html HTTP/1.0entonces emita el legado 302.
Ian Boyd
Parece 302 = 303 cuando se redirige.
vee
60

Un buen ejemplo de la 307 Internal Redirectacción es cuando Google Chrome encuentra una llamada HTTP a un dominio que sabe que requiere Seguridad de transporte estricta.

El navegador redirige sin problemas, utilizando el mismo método que la llamada original.

Redireccionamiento interno HTST 307

Kristian Williams
fuente
2
¿Sabes cuándo Google implementó esta función?
Tijme
2
Sí, aquí es donde veo que sucede: nuestro servidor no está enviando eso, en Chrome Devtools parece que es, pero solo Chrome está haciendo la redirección porque tenemos un encabezado de seguridad de transporte estricto
Mike Nelson el
16

Diagrama de flujo

  • 301: redirección permanente: la URL es antigua y debe reemplazarse. Los navegadores guardarán esto en caché.
    Ejemplo de uso: URL movida de /register-form.htmla signup-form.html.
    El método cambiará a GET, según RFC 7231: "Por razones históricas, un agente de usuario PUEDE cambiar el método de solicitud de POST a GET para la solicitud posterior".
  • 302: redireccionamiento temporal. Usar solo para clientes HTTP / 1.0. Este código de estado no debería cambiar el método, pero los navegadores lo hicieron de todos modos. El RFC dice: "Muchos agentes de usuario anteriores a HTTP / 1.1 no entienden [303]. Cuando la interoperabilidad con dichos clientes es una preocupación, se puede usar el código de estado 302, ya que la mayoría de los agentes de usuario reaccionan a una respuesta 302 como se describe aquí para 303. " Por supuesto, algunos clientes pueden implementarlo de acuerdo con las especificaciones, por lo que si la interoperabilidad con esos clientes antiguos no es una preocupación real, 303 es mejor para obtener resultados consistentes.
  • 303: redirección temporal, cambiando el método a GET.
    Ejemplo de uso: si el navegador envió POST a /register.php, ahora carga (GET) /success.html.
  • 307: redirección temporal, repitiendo la solicitud de forma idéntica.
    Ejemplo de uso: si el navegador envió una POST a /register.php, entonces esto le dice que rehaga la POST en /signup.php.
  • 308: redirección permanente, repitiendo la solicitud de forma idéntica. Cuando 307 es la contrapartida de "sin cambio de método" de 303, este estado 308 es la contrapartida de "sin cambio de método" de 301.

RFC 7231 (desde 2014) es muy legible y no demasiado detallado. Si quieres saber la respuesta exacta, es una lectura recomendada. Algunas otras respuestas usan RFC 2616 de 1999, pero nada cambió.

RFC 7238 especifica el estado 308. Se considera experimental, pero ya fue compatible con todos los principales navegadores en 2016.

Luc
fuente
302 no está en desuso.
Julian Reschke
@JulianReschke Wikipedia dice que "302 ha sido reemplazado por 303 y 307". Tal vez sea porque no soy un hablante nativo, pero para mí (en este contexto) reemplazado y en desuso significa lo mismo: usar 303 o 307, pero no 302. ¿Estoy leyendo esto mal?
Luc
Lo que está mal es la suposición de que Wikipedia tiene algo que decir al respecto. Si 302 fue desaprobado, el HTTP lo diría.
Julian Reschke
@JulianReschke Bastante justo, llevé a la fuente y waddayaknow? Tienes toda la razón. El RFC es realmente muy comprensible, y de hecho incluso recomiendan 302 bajo ciertas condiciones. Ninguno de los RFC "actualizados por" y "obsoletos por" mencionados anteriormente se refieren a códigos de estado, por lo que supongo que este documento de 1999 es de hecho el último que tenemos sobre él. Actualizaré mi respuesta.
Luc
Lo relevante es el registro del código de estado de la IANA y, por lo tanto, en este caso, RFC 7231.
Julian Reschke
8

ESPERADO para 302: la redirección utiliza el mismo método de solicitud POST en NEW_URL

CLIENT POST OLD_URL -> SERVER 302 NEW_URL -> CLIENT POST NEW_URL

ACTUAL para 302, 303: redirige el método de solicitud de cambios de POST a GET en NEW_URL

CLIENT POST OLD_URL -> SERVER 302 NEW_URL -> CLIENT GET NEW_URL (redirect uses GET)
CLIENT POST OLD_URL -> SERVER 303 NEW_URL -> CLIENT GET NEW_URL (redirect uses GET)

ACTUAL para 307: la redirección utiliza el mismo método de solicitud POST en NEW_URL

CLIENT POST OLD_URL -> SERVER 307 NEW_URL -> CLIENT POST NEW_URL
Roy Hyunjin Han
fuente
2

302 es una redirección temporal, que es generada por el servidor, mientras que 307 es una respuesta de redireccionamiento interno generada por el navegador. La redirección interna significa que la redirección se realiza automáticamente por el navegador internamente, básicamente el navegador altera la url ingresada de http a https en obtener la solicitud por sí mismo antes de realizar la solicitud, por lo que la solicitud de conexión no segura nunca se realiza a Internet. Si el navegador alterará la URL a https o no, depende de la lista de precarga de hsts que viene preinstalada con el navegador. También puede agregar cualquier sitio que admita https a la lista ingresando el dominio en la lista de precarga de hsts de su propio navegador que se encuentra en chrome: //net-internals/#hsts. Los propietarios de los dominios de sitios web pueden agregar algo más. para precargar la lista completando el formulario en https://hstspreload.org/por lo que viene preinstalado en los navegadores para cada usuario, aunque menciono que también puede hacerlo especialmente por usted mismo.


Permítanme explicarlo con un ejemplo:
hice una solicitud de obtención a http://www.pentesteracademy.com que solo admite https y no tengo ese dominio en mi lista de precarga de hsts en mi navegador ya que el propietario del sitio no se ha registrado en él venir con la lista de precarga de hsts preinstalada La solicitud GET para la versión no segura del sitio se redirige a la versión segura (consulte la ubicación con el encabezado http para eso en respuesta en la imagen de arriba). Ahora agrego el sitio a mi propia lista de precarga del navegador agregando su dominio en el formulario Agregar dominio hsts en chrome: // net-internals / # hsts, que modifica mi lista de precarga personal en mi navegador Chrome. Asegúrese de seleccionar incluir subdominios para Opción STS allí. Veamos la solicitud y la respuesta para el mismo sitio web ahora después de agregarlo a la lista de precarga de hsts.encabezados de solicitud y respuesta



encabezados de solicitud y respuesta
puede ver la redirección interna 307 allí en los encabezados de respuesta, en realidad esta respuesta es generada por su navegador y no por el servidor.
Además, la lista de precarga de HSTS puede ayudar a evitar que los usuarios lleguen a la versión no segura del sitio, ya que la redirección 302 es propensa a ataques mitm.
Espero haberte ayudado a entender más acerca de las redirecciones.

Simranjeet Singh
fuente
2

Originalmente solo había 302

| Response               | What browsers should do   |
|------------------------|---------------------------|
| 302 Found              | Redo request with new url |

La idea es que:

  • si estuviera haciendo una GETen algún lugar, volvería a hacer su GETa la nueva URL
  • si estuviera haciendo una POSTen algún lugar, volvería a hacer su POSTa la nueva URL
  • si estuviera haciendo una PUTen algún lugar, volvería a hacer su PUTa la nueva URL
  • si estuviera haciendo una DELETEen algún lugar, volvería a hacer su DELETEa la nueva URL
  • etc.

Lamentablemente, todos los navegadores lo hicieron mal. Al obtener un 302, siempre cambiarían a GETla nueva URL, en lugar de volver a intentar la solicitud con el mismo verbo ( por ejemplo , POST):

  • Mosaico lo hizo mal
  • Netscape copió los errores en mosaico; entonces se equivocaron
  • Internet Explorer copió los errores en Netscape; entonces se equivocaron

Se volvió de facto incorrecto.

Todos los navegadores se 302equivocaron. Así 303y 307fueron creados.

El | Respuesta | ¿Qué deberían hacer los navegadores? Lo que realmente hacen los navegadores | | ------------------------ | ------------------------ --- | --------------------------- | El | 302 encontrado | Rehacer solicitud con nueva url | OBTENER con nueva url | El | 303 Ver otros | OBTENER con nueva url | OBTENER con nueva url | El | Redirección temporal 307 | Rehacer solicitud con nueva url | Rehacer solicitud con nueva url |

En forma de cuadro

Los 5 tipos diferentes de redireccionamientos:

╔═══════════╤════════════════════════════════════════════════╗
║           │                Switch to GET?                  ║
║ Temporary │          No            │         Yes           ║
╠═══════════╪════════════════════════╪═══════════════════════╣
║ No        │ 308 Permanent Redirect │ 301 Moved Permanently ║
╟───────────┼────────────────────────┼───────────────────────╢
║ Yes       │ 307 Temporary Redirect │ 303 See Other         ║
║           │ 302 Found (intended)   │ 302 Found (actual)    ║
╚═══════════╧════════════════════════╧═══════════════════════╝

Alternativamente:

| Response                 | Switch to get? | Temporary? |
|--------------------------|----------------|------------|
| 301 Moved Permanently    | No             | No         |
| 302 Found (intended)     | No             | Yes        |
| 302 Found (actual)       | Yes            | Yes        |
| 303 See Other            | Yes            | Yes        |
| 307 Temporary Redirect   | No             | Yes        |
| 308 Permanent Redirect   | No             | No         |
Ian Boyd
fuente
1

Además, para los administradores del servidor, puede ser importante tener en cuenta que los navegadores pueden presentar un aviso al usuario si utiliza la redirección 307.

Por ejemplo *, Firefox y Opera le pedirían al usuario permiso para redirigir, mientras que Chrome, IE y Safari lo harían de forma transparente.

* según Bulletproof SSL y TLS (página 192).

Pacerier
fuente
Eso solo es cierto para solicitudes inseguras, como POST.
Julian Reschke
0

En algunos casos de uso, un atacante puede abusar de las redirecciones 307 para conocer las credenciales de la víctima.

Se puede encontrar más información en la sección 3.1 de Un análisis integral de seguridad formal de OAuth 2.0 .

Los autores del artículo anterior sugieren lo siguiente:

Reparar. Contrariamente a la redacción actual en el estándar OAuth, el método exacto de la redirección no es un detalle de implementación sino esencial para la seguridad de OAuth. En el estándar HTTP ( RFC 7231 ), solo la redirección 303 se define sin ambigüedades para descartar el cuerpo de una solicitud HTTP POST. Todos los demás códigos de estado de redirección HTTP, incluido el 302 más utilizado, dejan al navegador la opción de preservar la solicitud POST y los datos del formulario. En la práctica, los navegadores generalmente reescriben a una solicitud GET, por lo que descartan los datos del formulario, excepto los redireccionamientos 307. Por lo tanto, el estándar OAuth debería requerir redireccionamientos 303 para los pasos mencionados anteriormente para solucionar este problema.

MS Dousti
fuente