Qual é a diferença entre um redirecionamento 302 e um 307?

208

Qual é a diferença entre uma resposta 302 FOUNDe uma 307 TEMPORARY REDIRECTresposta HTTP?

A especificação W3 parece indicar que os dois são usados ​​para redirecionamentos temporários e nem podem ser armazenados em cache, a menos que a resposta permita especificamente.

Zach Hirsch
fonte

Respostas:

99

As preocupações de diferença de redirecionamento POST, PUTe DELETEpedidos e quais são as expectativas do servidor são para o comportamento do agente ( RFC 2616):

Nota: RFC 1945 e RFC 2068 especificam que o cliente não tem permissão para alterar o método na solicitação redirecionada. No entanto, a maioria das implementações de agentes de usuários existentes tratam 302 como se fosse uma resposta 303, executando um GET no valor do campo Local, independentemente do método de solicitação original. Os códigos de status 303 e 307 foram adicionados para servidores que desejam deixar inequivocamente claro que tipo de reação é esperada do cliente.

Leia também o artigo da Wikipedia sobre os códigos de redirecionamento 30x .

Franci Penov
fonte
Então, da perspectiva do analisador / agente / navegador, podemos simplesmente tratar 302 e 307 como idênticos, certo? (O exato mesmo pedaço de código pode ser usado para lidar com ambos os casos sem mais distinguishment?)
Pacerier
Não - você pode tratar 302 e 303 como idênticos, mas 307 é diferente.
Quentin Skousen
@kkhugs, De jeito nenhum, é necessário um navegador 1.0 para fazer o get-302 da mesma forma que o get-307 é feito nos navegadores 1.1. Um navegador 1.0 é necessário para executar o post-302 da mesma maneira que o get-302, exceto que ele deve primeiro exigir uma confirmação do usuário para continuar e o método deve ser postado.
Pacerier 15/02
É necessário um navegador 1.1 para executar o get-302 da mesma forma que o get-307.
Pacerier 15/02
161

307 surgiu porque os agentes usuários adotados como de fato comportamento receber solicitações POST que recebem uma resposta 302 e enviam uma solicitação GET ao cabeçalho da resposta Localização.

Esse é o comportamento incorreto - apenas um 303 deve fazer com que um POST se transforme em um GET. Os agentes do usuário devem (mas não) seguir o método POST ao solicitar o novo URL se a solicitação POST original retornar 302.

307 foi introduzido para permitir que os servidores deixassem claro para o agente do usuário que uma alteração de método não deveria ser feita pelo cliente ao seguir o cabeçalho de resposta Localização.

Christopher Orr
fonte
3
Algum exemplo de agente de usuário que responde incorretamente? Geralmente é uma porcentagem muito pequena de visitantes?
goodguys_activate
6
@ makerofthings7 Todos os navegadores manipulam 302incorretamente. Chrome 30, IE10. Tornou-se a implementação incorreta de fato ; isso não pode ser alterado porque muitos sites emitem por engano o problema 302. De fato, o ASP.net MVC emite incorretamente o 302, dependendo do fato de os navegadores o tratarem incorretamente.
Ian Boyd
1
As estruturas de razão do @IanBoyd Only fazem isso porque 303também foram introduzidas 307na especificação HTTP 1.1 e, portanto, permitem compatibilidade retroativa com agentes de usuário HTTP 1.0. Obviamente, a verdadeira questão é: ainda deveríamos estar lidando com agentes de usuário HTTP 1.0?
ewanm89
1
@ ewanm89 Parece ser que o quadro poderia criar o método de resposta devidamente nomeado (por exemplo Response.RedirectSeeOther), e se o cliente não é 1.1 (por exemplo GET /foo.html, GET /foo.html HTTP/1.0), em seguida, emitir o legado 302.
Ian Boyd
Parece 302 = 303 quando redirecionado.
vee
60

Um bom exemplo da 307 Internal Redirectação em ação é quando o Google Chrome encontra uma chamada HTTP para um domínio conhecido como exigindo segurança estrita de transporte.

O navegador é redirecionado sem problemas, usando o mesmo método da chamada original.

Redirecionamento interno do HTST 307

Kristian Williams
fonte
2
Você sabe quando o Google implementou esse recurso?
Tijme
2
Sim, é aqui que estou vendo isso acontecer - nosso servidor não está enviando isso - no chrome devtools parece que é, mas é apenas chrome fazendo o redirecionamento porque temos um cabeçalho Strict Transport Security
mike nelson
16

Fluxograma

  • 301: redirecionamento permanente: o URL é antigo e deve ser substituído. Os navegadores armazenarão isso em cache.
    Exemplo de uso: URL movido de /register-form.htmlpara signup-form.html.
    O método será alterado para GET, conforme RFC 7231: "Por razões históricas, um agente do usuário PODE alterar o método de solicitação de POST para GET para a solicitação subseqüente".
  • 302: redirecionamento temporário. Use apenas para clientes HTTP / 1.0.Esse código de status não deve alterar o método, mas os navegadores fizeram isso de qualquer maneira. A RFC diz: "Muitos agentes de usuário pré-HTTP / 1.1 não entendem [303]. Quando a interoperabilidade com esses clientes é uma preocupação, o código de status 302 pode ser usado, pois a maioria dos agentes de usuário reage a uma resposta 302, conforme descrito aqui. para 303. " Certamente, alguns clientes podem implementá-lo de acordo com as especificações, portanto, se a interoperabilidade com esses clientes antigos não é uma preocupação real, 303 é melhor para obter resultados consistentes.
  • 303: redirecionamento temporário, alterando o método para GET.
    Exemplo de uso: se o navegador enviou o POST para /register.php, agora carregue (GET) /success.html.
  • 307: redirecionamento temporário, repetindo a solicitação de forma idêntica.
    Exemplo de uso: se o navegador enviou um POST para /register.php, isso indica para refazer o POST em /signup.php.
  • 308: redirecionamento permanente, repetindo a solicitação de forma idêntica. Onde 307 é a contrapartida "sem alteração de método" de 303, esse status 308 é a contraparte "sem alteração de método" de 301.

O RFC 7231 (de 2014) é muito legível e não muito detalhado. Se você quiser saber a resposta exata, é uma leitura recomendada. Algumas outras respostas usam o RFC 2616 de 1999, mas nada mudou.

RFC 7238 especifica o status 308. É considerado experimental, mas já era suportado por todos os principais navegadores em 2016.

Luc
fonte
302 não está obsoleto.
Julian Reschke
@JulianReschke A Wikipedia diz que "302 foi substituído por 303 e 307". Talvez seja porque eu não sou um falante nativo, mas para mim (neste contexto) substituído e reprovado significa o mesmo: use 303 ou 307, mas não 302. Estou lendo isso errado?
Luc
O que há de errado é a suposição de que a Wikipedia tem uma palavra a dizer sobre isso. Se 302 foi descontinuado, o HTTP diria isso.
Julian Reschke
@JulianReschke Fair o suficiente, eu levei para a fonte e waddayaknow? Você está completamente certo. O RFC é realmente muito compreensível e, de fato, eles recomendam o 302 sob certas condições. Nenhum dos RFCs "atualizados por" e "obsoletos por" mencionados acima é sobre códigos de status, então acho que este documento de 1999 é realmente o mais recente que temos nele. Vou atualizar minha resposta.
Luc
O que é relevante é o registro do código de status IANA, e, portanto, neste caso, RFC 7231.
Julian Reschke
8

ESPERADO para 302: o redirecionamento usa o mesmo método de solicitação POST em NEW_URL

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

ACTUAL para 302, 303: redirecione o método de solicitação de alterações de POST para GET em 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: o redirecionamento usa o mesmo método de solicitação POST em NEW_URL

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

302 é redirecionamento temporário, que é gerado pelo servidor, enquanto 307 é uma resposta de redirecionamento interno gerada pelo navegador. Redirecionamento interno significa que o redirecionamento é feito automaticamente pelo navegador internamente, basicamente o navegador altera a URL inserida de http para https na solicitação get antes de fazer a solicitação, para que a solicitação de conexão não segura nunca seja feita na Internet. Se o navegador alterará ou não o URL para https depende da lista de pré-carregamento do hsts que vem pré-instalada com o navegador. Você também pode adicionar qualquer site que suporte https à lista inserindo o domínio na lista de pré-carregamento hsts do seu próprio navegador, que está no chrome: //net-internals/#hsts. para pré-carregar a lista preenchendo o formulário em https://hstspreload.org/para que ele seja pré-instalado nos navegadores para todos os usuários, mesmo que eu mencione que você também pode fazer isso especialmente por você.


Deixe-me explicar com um exemplo:
fiz uma solicitação de obtenção para http://www.pentesteracademy.com que suporta apenas https e não tenho esse domínio na minha lista de pré-carregamento de hsts no meu navegador, pois o proprietário do site não se registrou para ele para vir com a lista de pré-carregamento de hsts pré-instalados. A solicitação GET para uma versão não segura do site é redirecionada para uma versão segura (consulte o cabeçalho http nomeado local para isso em resposta na imagem acima). Agora, adiciono o site à minha própria lista de pré-carregamento do navegador adicionando seu domínio no formulário Adicionar domínio hsts no chrome: // net-internals / # hsts, que modifica minha lista de pré-carregamento pessoal no navegador chrome. Opção STS lá. Vamos ver a solicitação e resposta para o mesmo site agora depois de adicioná-lo à lista de pré-carregamento do hsts.cabeçalhos de solicitação e resposta



cabeçalhos de solicitação e resposta
você pode ver o redirecionamento interno 307 nos cabeçalhos de resposta; na verdade, essa resposta é gerada pelo navegador e não pelo servidor.
Também a lista de pré-carregamento do HSTS pode ajudar a impedir que os usuários alcancem a versão não segura do site, pois o redirecionamento 302 é propenso a ataques mitm.
Espero ter ajudado você a entender mais sobre redirecionamentos.

Simranjeet Singh
fonte
2

Originalmente havia apenas 302

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

A ideia é que:

  • se você estivesse fazendo isso GETem algum local, refizesse o seu GETpara o novo URL
  • se você estivesse fazendo isso POSTem algum local, refizesse o seu POSTpara o novo URL
  • se você estivesse fazendo isso PUTem algum local, refizesse o seu PUTpara o novo URL
  • se você estivesse fazendo isso DELETEem algum local, refizesse o seu DELETEpara o novo URL
  • etc

Infelizmente, todos os navegadores fizeram errado. Ao obter um 302, eles sempre mudam para GETo novo URL, em vez de tentar novamente a solicitação com o mesmo verbo ( por exemplo , POST):

  • Mosaic fez errado
  • O Netscape copiou os erros no Mosaic; então eles entenderam errado
  • O Internet Explorer copiou os erros no Netscape; então eles entenderam errado

Tornou-se de fato errado.

Todos os navegadores estão 302errados. Então 303e 307foram criados.

| Resposta O que os navegadores devem fazer | O que os navegadores realmente fazem | | ------------------------ | ------------------------ --- | --------------------------- | | 302 encontrado | Refazer solicitação com novo URL | GET com novo URL | | 303 Ver outros | GET com novo URL | GET com novo URL | | 307 Redirecionamento temporário | Refazer solicitação com novo URL | Refazer solicitação com novo URL |

Em forma de gráfico

Os 5 tipos diferentes de redirecionamentos:

╔═══════════╤════════════════════════════════════════════════╗
║           │                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
fonte
1

Além disso, para administradores de servidor, pode ser importante observar que os navegadores podem apresentar um prompt ao usuário se você usar o redirecionamento 307.

Por exemplo *, o Firefox e o Opera solicitam ao usuário permissão para redirecionar, enquanto o Chrome, o IE e o Safari fazem o redirecionamento de forma transparente.

* por SSL e TLS à prova de balas (página 192).

Pacerier
fonte
Isso é verdade apenas para solicitações inseguras, como POST.
Julian Reschke
0

Em alguns casos de uso, os redirecionamentos 307 podem ser abusados ​​por um invasor para aprender as credenciais da vítima.

Informações adicionais podem ser encontradas na seção 3.1 de Uma análise formal abrangente da segurança do OAuth 2.0 .

Os autores do artigo acima sugerem o seguinte:

Consertar. Ao contrário do texto atual no padrão OAuth, o método exato do redirecionamento não é um detalhe de implementação, mas essencial para a segurança do OAuth. No padrão HTTP ( RFC 7231 ), apenas o redirecionamento 303 é definido sem ambiguidade para descartar o corpo de uma solicitação HTTP POST. Todos os outros códigos de status de redirecionamento HTTP, incluindo o 302 mais comumente usado, deixam ao navegador a opção de preservar a solicitação POST e os dados do formulário. Na prática, os navegadores geralmente reescrevem para uma solicitação GET, eliminando assim os dados do formulário, exceto os redirecionamentos 307. Portanto, o padrão OAuth deve exigir 303 redirecionamentos para as etapas mencionadas acima, a fim de corrigir esse problema.

MS Dousti
fonte