Qual è la differenza tra un reindirizzamento 302 e un 307?


208

Qual è la differenza tra a 302 FOUNDe a307 TEMPORARY REDIRECT risposta ae HTTP?

Le specifiche W3 sembrano indicare che sono entrambe utilizzate per reindirizzamenti temporanei e nessuna delle due può essere memorizzata nella cache a meno che la risposta non lo consenta espressamente.

Risposte:


99

Le preoccupazioni differenza reindirizzamento POST, PUTe DELETEle richieste e quali sono le aspettative del server sono per il comportamento user agent ( RFC 2616):

Nota: RFC 1945 e RFC 2068 specificano che al client non è consentito modificare il metodo sulla richiesta reindirizzata. Tuttavia, la maggior parte delle implementazioni degli user agent esistenti considera 302 come se fosse una risposta 303, eseguendo un GET sul valore del campo Posizione indipendentemente dal metodo di richiesta originale. I codici di stato 303 e 307 sono stati aggiunti per i server che desiderano chiarire in modo inequivocabile il tipo di reazione prevista per il client.

Inoltre, leggi l'articolo di Wikipedia sui codici di reindirizzamento 30x .


Quindi, dal punto di vista del parser / agente / browser, possiamo semplicemente considerare 302 e 307 identici, giusto? (L' esatto stesso pezzo di codice può essere utilizzato per gestire entrambi i casi senza ulteriori distinguishment?)
Pacerier

No: puoi trattare 302 e 303 come identici, ma 307 è diverso.
Quentin Skousen,

@kkhugs, In nessun caso è necessario un browser 1.0 per fare get-302 allo stesso modo di get-307 nei browser 1.1. È necessario un browser 1.0 per eseguire post-302 allo stesso modo di get-302, tranne per il fatto che deve prima richiedere una conferma utente per procedere e il metodo deve essere post.
Pacerier,

È necessario un browser 1.1 per fare get-302 allo stesso modo di get-307.
Pacerier

161

307 è nato perché gli user agent hanno adottato di fatto un comportamento per accettare le richieste POST che ricevono una risposta 302 e inviare una richiesta GET all'intestazione della risposta della posizione.

Questo è un comportamento errato : solo un 303 dovrebbe far sì che un POST si trasformi in un GET. Gli interpreti dovrebbero (ma non) attenersi al metodo POST quando si richiede il nuovo URL se la richiesta POST originale ha restituito un 302.

307 è stato introdotto per consentire ai server di chiarire all'agente utente che il client non deve apportare una modifica del metodo quando segue l'intestazione della risposta della posizione.


3
Qualche esempio di user agent che rispondono in modo errato? Di solito è una percentuale molto piccola di visitatori?
goodguys_activate

6
@ makerofthings7 Tutti i browser 302non vengono gestiti correttamente. Chrome 30, IE10. È diventata di fatto un'implementazione errata; che non può essere modificato perché così tanti siti web emettono erroneamente 302. In realtà ASP.net MVC emette erroneamente 302, a seconda del fatto che i browser lo gestiscono in modo errato.
Ian Boyd,

1
@IanBoyd L'unico motivo per cui i framework lo fanno è perché è 303stato introdotto anche 307nella specifica HTTP 1.1 e quindi consente la retrocompatibilità con i programmi utente HTTP 1.0. Naturalmente, la vera domanda è: dovremmo ancora gestire gli user agent HTTP 1.0 adesso?
ewanm89,

1
@ ewanm89 Sembra che il framework possa creare il metodo di risposta correttamente chiamato (ad es. Response.RedirectSeeOther) e se il client non è 1.1 (ad es GET /foo.html. GET /foo.html HTTP/1.0) quindi rilasciare l'eredità 302.
Ian Boyd,

Sembra 302 = 303 quando reindirizza.
Vee

60

Un buon esempio 307 Internal Redirectdell'azione è quando Google Chrome incontra una chiamata HTTP a un dominio che conosce come esigente Sicurezza del trasporto rigorosa.

Il browser reindirizza senza problemi, utilizzando lo stesso metodo della chiamata originale.

HTST 307 Reindirizzamento interno


2
Sai quando Google ha implementato questa funzione?
Tijme,

2
Sì, è qui che lo vedo accadere - il nostro server non lo sta inviando - in Chrome Devtools sembra che sia ma è solo Chrome che sta eseguendo il reindirizzamento perché abbiamo un'intestazione di Sicurezza del trasporto rigorosa
Mike Nelson,

16

Diagramma di flusso

  • 301: reindirizzamento permanente: l'URL è vecchio e deve essere sostituito. I browser lo memorizzeranno nella cache.
    Esempio di utilizzo: URL spostato da /register-form.htmla signup-form.html.
    Il metodo cambierà in GET, come da RFC 7231: "Per motivi storici, un agente utente PU change cambiare il metodo di richiesta da POST a GET per la richiesta successiva."
  • 302: reindirizzamento temporaneo. Utilizzare solo per client HTTP / 1.0.Questo codice di stato non dovrebbe cambiare il metodo, ma i browser lo hanno fatto comunque. La RFC afferma: "Molti agenti utente pre-HTTP / 1.1 non comprendono [303]. Quando l'interoperabilità con tali client è un problema, è possibile utilizzare invece il codice di stato 302, poiché la maggior parte degli agenti utente reagisce a una risposta 302 come descritto qui per 303. " Naturalmente, alcuni clienti potrebbero implementarlo secondo le specifiche, quindi se l'interoperabilità con clienti così antichi non è una vera preoccupazione, 303 è meglio per risultati coerenti.
  • 303: reindirizzamento temporaneo, cambiando il metodo in GET.
    Esempio di utilizzo: se il browser ha inviato POST a /register.php, ora carica (GET) /success.html.
  • 307: reindirizzamento temporaneo, ripetendo la richiesta in modo identico.
    Esempio di utilizzo: se il browser ha inviato un POST a /register.php, allora questo gli dice di ripetere il POST a /signup.php.
  • 308: reindirizzamento permanente, ripetendo la richiesta in modo identico. Dove 307 è la controparte "nessuna modifica del metodo" di 303, questo stato 308 è la controparte "nessuna modifica del metodo" di 301.

RFC 7231 (dal 2014) è molto leggibile e non eccessivamente dettagliato. Se vuoi conoscere la risposta esatta, è una lettura consigliata. Alcune altre risposte usano RFC 2616 del 1999, ma nulla è cambiato.

RFC 7238 specifica lo stato 308. È considerato sperimentale, ma era già supportato da tutti i principali browser nel 2016.


302 non è obsoleto.
Julian Reschke,

@JulianReschke Wikipedia afferma che "302 è stato sostituito da 303 e 307." Forse è perché non sono un madrelingua, ma per me (in questo contesto) sostituito e deprecato significa lo stesso: utilizzare 303 o 307, ma non 302. Sto leggendo questo male?
Luc

Ciò che è sbagliato è l'ipotesi che Wikipedia abbia voce in capitolo. Se 302 fosse deprecato, HTTP lo direbbe.
Julian Reschke,

@JulianReschke Abbastanza giusto, ho preso alla fonte e waddayaknow? Hai perfettamente ragione. La RFC è in realtà molto comprensibile, e in effetti raccomandano addirittura 302 in determinate condizioni. Nessuna delle RFC "aggiornate da" e "obsolete" menzionate in alto riguarda i codici di stato, quindi immagino che questo documento del 1999 sia davvero l'ultimo che abbiamo su di esso. Aggiornerò la mia risposta.
Luc

Ciò che è rilevante è il registro dei codici di stato IANA, e quindi, in questo caso, RFC 7231.
Julian Reschke

8

PREVISTO per 302: il reindirizzamento utilizza lo stesso metodo di richiesta POST su NEW_URL

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

ATTIVO per 302, 303: reindirizzare il metodo di richiesta di modifiche da POST a GET su 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)

ATTUALE per 307: il reindirizzamento utilizza lo stesso metodo di richiesta POST su NEW_URL

CLIENT POST OLD_URL -> SERVER 307 NEW_URL -> CLIENT POST NEW_URL

2

302 è il reindirizzamento temporaneo, che viene generato dal server mentre 307 è la risposta di reindirizzamento interno generata dal browser. Il reindirizzamento interno significa che il reindirizzamento viene eseguito automaticamente dal browser internamente, in pratica il browser modifica l'URL immesso da http a https per ottenere la richiesta da solo prima di effettuare la richiesta, quindi la richiesta di connessione non protetta non viene mai effettuata a Internet. Il fatto che il browser cambi o meno l'URL in https dipende dall'elenco di precaricamento hsts preinstallato con il browser. Puoi anche aggiungere qualsiasi sito che supporti https all'elenco inserendo il dominio nell'elenco di precaricamento hsts del tuo browser che è in chrome: //net-internals/#hsts.Un altro dominio di siti Web può essere aggiunto dai proprietari per precaricare l'elenco compilando il modulo in https://hstspreload.org/in modo che venga preinstallato nei browser per ogni utente anche se menziono che puoi fare particolarmente anche per te stesso.


Lasciatemi spiegare con un esempio:
ho fatto una richiesta get a http://www.pentesteracademy.com che supporta solo https e non ho quel dominio nel mio elenco di precaricamento hsts sul mio browser poiché il proprietario del sito non si è registrato per questo a venire con l'elenco precaricato hsts preinstallato. La richiesta GET per la versione non protetta del sito viene reindirizzata alla versione protetta (vedere la posizione dell'intestazione http per quella in risposta nell'immagine sopra). Ora aggiungo il sito al mio elenco di precaricamenti del browser aggiungendo il suo dominio nel modulo Aggiungi dominio hsts su chrome: // net-internals / # hsts, che modifica il mio elenco di precarichi personali sul mio browser Chrome. Assicurati di selezionare Includi sottodomini per Opzione STS lì. Vediamo ora la richiesta e la risposta per lo stesso sito Web dopo averlo aggiunto all'elenco di precaricamento hsts.intestazioni di richiesta e risposta



intestazioni di richiesta e risposta
puoi vedere il reindirizzamento interno 307 lì nelle intestazioni di risposta, in realtà questa risposta è generata dal tuo browser non dal server.
Anche l'elenco di precaricamento HSTS può aiutare a impedire agli utenti di raggiungere la versione non sicura del sito poiché 302 reindirizzamenti sono inclini a mitigare gli attacchi.
Spero di averti aiutato in qualche modo a capire meglio i reindirizzamenti.


2

Inizialmente c'era solo 302

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

L'idea è che:

  • se stavi eseguendo una ricerca GETin qualche posizione, dovresti rifare il tuo GETal nuovo URL
  • se stavi eseguendo una ricerca POSTin qualche posizione, dovresti rifare il tuo POSTal nuovo URL
  • se stavi eseguendo una ricerca PUTin qualche posizione, dovresti rifare il tuo PUTal nuovo URL
  • se stavi eseguendo una ricerca DELETEin qualche posizione, dovresti rifare il tuo DELETEal nuovo URL
  • eccetera

Purtroppo ogni browser ha sbagliato. Quando ottengono un 302, passerebbero sempre GETal nuovo URL, piuttosto che riprovare la richiesta con lo stesso verbo ( ad es . POST):

  • Mosaic ha sbagliato
  • Netscape ha copiato i bug in Mosaic; quindi hanno sbagliato
  • Internet Explorer ha copiato i bug in Netscape; quindi hanno sbagliato

È diventato di fatto sbagliato.

Tutti i browser hanno 302sbagliato. Quindi 303e 307sono stati creati.

| Risposta | Cosa dovrebbero fare i browser | Cosa fanno effettivamente i browser | | ------------------------ | ------------------------ --- | --------------------------- | | 302 trovati | Ripeti richiesta con nuovo URL | OTTIENI con il nuovo URL | | 303 Vedi Altro | OTTIENI con il nuovo URL | OTTIENI con il nuovo URL | | 307 Reindirizzamento temporaneo | Ripeti richiesta con nuovo URL | Ripeti richiesta con nuovo URL |

In forma di grafico

I 5 diversi tipi di reindirizzamenti:

╔═══════════╤════════════════════════════════════════════════╗
║           │                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)    ║
╚═══════════╧════════════════════════╧═══════════════════════╝

In alternativa:

| 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         |

1

Inoltre, per gli amministratori del server, potrebbe essere importante notare che i browser possono presentare una richiesta all'utente se si utilizza il reindirizzamento 307.

Ad esempio *, Firefox e Opera chiedono all'utente il permesso di reindirizzare, mentre Chrome, IE e Safari eseguono il reindirizzamento in modo trasparente.

* per SSL e TLS antiproiettile (pagina 192).


Questo è vero solo per richieste non sicure, come POST.
Julian Reschke,

0

In alcuni casi d'uso, 307 reindirizzamenti potrebbero essere abusati da un utente malintenzionato per apprendere le credenziali della vittima.

Ulteriori informazioni sono disponibili nella sezione 3.1 di Un'analisi di sicurezza formale completa di OAuth 2.0 .

Gli autori del documento sopra suggeriscono quanto segue:

Fix. Contrariamente all'attuale formulazione dello standard OAuth, il metodo esatto del reindirizzamento non è un dettaglio di implementazione ma essenziale per la sicurezza di OAuth. Nello standard HTTP ( RFC 7231 ), solo il reindirizzamento 303 viene definito in modo univoco per eliminare il corpo di una richiesta POST HTTP. Tutti gli altri codici di stato di reindirizzamento HTTP, incluso il 302 più comunemente usato, lasciano al browser l'opzione per preservare la richiesta POST e i dati del modulo. In pratica, i browser in genere riscrivono su una richiesta GET, eliminando così i dati del modulo, ad eccezione di 307 reindirizzamenti. Pertanto, lo standard OAuth dovrebbe richiedere 303 reindirizzamenti per i passaggi sopra menzionati per risolvere questo problema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.