rest error Correggere il codice di stato http per la risorsa che richiede l'autorizzazione




rest error status code (7)

Sembra che ci sia molta confusione sul corretto codice di stato http da restituire se l'utente tenta di accedere a una pagina che richiede l'accesso dell'utente.

Quindi in pratica quale codice di stato verrà inviato quando mostrerò la pagina di accesso?

Sono abbastanza sicuro che abbiamo bisogno di usare un codice di stato nella gamma 4xx .

Non sto parlando di autenticazione HTTP qui, quindi questo è almeno un codice di stato che non useremo ( 401 Unauthorized ).

Ora cosa dovremmo usare? Le risposte (anche qui su SO) sembrano variare:

Secondo la risposta here dovremmo usare 403 Forbidden .

Ma nella descrizione del codice di stato è:

L'autorizzazione non aiuterà e la richiesta NON DEVE essere ripetuta.

Beh, non sembra quello giusto. Dal momento che l'autorizzazione potrebbe aiutare.

Diamo un'occhiata ad un'altra risposta. La risposta here non usa affatto la gamma 4xx ma utilizza 302 Found

La descrizione del 302 Found codice di stato 302 Found :

La risorsa richiesta risiede temporaneamente in un URI diverso. Poiché il reindirizzamento potrebbe essere modificato occasionalmente, il client DOVREBBE continuare a utilizzare l'URI di richiesta per richieste future. Questa risposta è memorizzabile nella cache solo se indicata da un campo di intestazione Cache-Control o Expires.

Penso che anche questo non sia quello che voglio. Poiché non è la risorsa richiesta che risiede in un URI differente. Ma piuttosto una risorsa completamente diversa (pagina di accesso vs pagina di contenuto autenticato).

Così mi sono trasferito e ho colto un'altra answer sorprendentemente con un'altra soluzione.

Questa risposta suggerisce di scegliere 400 Bad Request .

La descrizione di questo codice di stato è:

La richiesta non può essere compresa dal server a causa di una sintassi errata. Il cliente NON DOVREBBE ripetere la richiesta senza modifiche.

Penso che il server abbia capito bene la richiesta, ma si rifiuta di dare l'accesso prima che l'utente sia autenticato.

Un'altra answer dice anche che una risposta 403 è corretta, tuttavia termina con:

Se si tratta di un sito Web pubblico in cui si tenta di negare l'accesso in base a un cookie di sessione [è quello che faccio], 200 con un corpo appropriato per indicare che è necessario il login o un reindirizzamento temporaneo 302 a una pagina di accesso è spesso migliore.

Quindi 403 è corretto, ma 200 o 302 è IL MEGLIO.

Hey! Questo è quello che sto cercando: la soluzione migliore. Ma il meglio non dovrebbe essere lo stesso di quello giusto? E perché sarebbe il migliore?

Grazie a tutti coloro che sono arrivati ​​così lontano in questa domanda :)

So che non dovrei preoccuparmi troppo di questo. E penso che questa domanda sia più ipotetica (non proprio, ma usata per mancanza di una parola migliore).

Ma questa domanda mi sta perseguitando da un po 'di tempo.

E se io fossi stato un manager (che ha appena preso alcune parole dal suono fresco come fanno sempre) avrei detto: ma, ma, ma, ma la tranquillità è importante. :-)

Quindi: qual è the right way™ di utilizzare un codice di stato nella situazione sopra (se presente)?

tl; dr

Qual è la risposta corretta del codice di stato http quando un utente tenta di accedere a una pagina che richiede l'accesso?


Come si fa notare, 403 Forbidden è esplicitamente definito con la frase " Autorizzazione non aiuta ", ma vale la pena notare che gli autori si riferivano quasi certamente all'autorizzazione HTTP (che non sarà di certo d'aiuto poiché il tuo sito utilizza un diverso schema di autorizzazione ). Infatti, dato che il codice di stato è un segnale per l' agente utente piuttosto che per l' utente , tale codice sarebbe corretto nella misura in cui qualsiasi autorizzazione che l'agente tenta di fornire non sarà più di aiuto con il processo di autorizzazione richiesto (cf 401 Unauthorized ).

Tuttavia, se si prende letteralmente la definizione di 403 Forbidden e si ritiene che sia ancora inappropriata, potrebbe applicarsi il 409 Conflict ? Come definito nella RFC 2616 §10.4.10 :

   The request could not be completed due to a conflict with the current
   state of the resource. This code is only allowed in situations where
   it is expected that the user might be able to resolve the conflict
   and resubmit the request. The response body SHOULD include enough
   information for the user to recognize the source of the conflict.
   Ideally, the response entity would include enough information for the
   user or user agent to fix the problem; however, that might not be
   possible and is not required.

Esiste effettivamente un conflitto con lo stato attuale della risorsa: la risorsa è in uno stato "bloccato" e tale conflitto può essere "risolto" solo attraverso l'utente che fornisce le proprie credenziali e invia nuovamente la richiesta. Il corpo includerà " sufficienti informazioni per l'utente per riconoscere l'origine del conflitto " (dichiarerà che non sono loggati) e in effetti includerà anche " informazioni sufficienti per l'utente o il programma utente per risolvere il problema " ( cioè un modulo di accesso).


Il tuo "TL; DR" non corrisponde alla versione "TL".

La risposta corretta per richiedere una risorsa per cui è necessaria l'autorizzazione per richiedere è 401.

302 non è la risposta corretta, perché, in effetti, la risorsa non è disponibile altrove. L'URL originale era corretto, il cliente semplicemente non aveva i diritti. Se segui il reindirizzamento, in realtà non ottieni ciò che stai cercando. Vieni lasciato cadere in un flusso di lavoro ad hoc che non ha nulla a che fare con la risorsa.

403 non è corretto. 403 è l'errore "impossibile arrivare da qui". Semplicemente non puoi vederlo, non mi interessa chi sei. Alcuni sostengono che il 403 e il 404 sono simili. La differenza è semplicemente con 403, il server sta dicendo "sì, ce l'ho, ma non puoi", mentre 404 dice "Non so nulla di ciò di cui stai parlando". I vincitori della sicurezza affermerebbero che 404 è "più sicuro". Perché dire loro qualcosa che non hanno bisogno di sapere.

Il problema riscontrato non ha nulla a che fare con REST o HTTP. Il tuo problema è cercare di impostare una relazione di stato tra il client e il server, manifestata alla fine tramite alcuni cookie. L'intera risorsa -> 302 -> Pagina di accesso è tutta basata sull'esperienza utente utilizzando l'hack noto come browser Web, che risulta essere entrambi, in forma di magazzino, un client HTTP schifoso e un pessimo partecipante REST.

HTTP ha un meccanismo di autorizzazione. L'intestazione di autorizzazione. L'esperienza dell'utente intorno ad esso, in un browser generico, è orribile. Quindi nessuno lo usa.

Quindi non c'è una risposta HTTP corretta (beh, 401, ma non / non può usarlo). Non esiste una risposta REST adeguata, poiché REST si basa in genere sul protocollo sottostante (HTTP in questo caso, ma lo abbiamo già affrontato).

Così. 302 -> 200 per la pagina di accesso è tutto ciò che ha scritto. Questo è ciò che ottieni. Se non stavi usando il browser, o facevi tutto tramite XHR o qualche altro client personalizzato, questo non sarebbe un problema. Dovresti semplicemente usare l'intestazione Authorization, seguire il protocollo HTTP e sfruttare uno schema come DIGEST o cosa AWS usa e fare. Quindi è possibile utilizzare gli standard appropriati per rispondere a domande come queste.


Concordato. REST è solo uno stile, non un protocollo rigoroso. Molti servizi web pubblici si discostano da questo stile. Puoi costruire il tuo servizio per restituire quello che vuoi. Assicurati solo che i tuoi clienti sappiano come aspettarsi i codici di ritorno.

Personalmente, ho sempre usato 401 (non autorizzato) per indicare che un utente non autenticato ha richiesto una risorsa che richiede un accesso. Quindi richiedo all'applicazione client di guidare l'utente al login.

Io uso 400 (richiesta errata) in risposta a un tentativo di accesso con credenziali non valide.

HTTP 302 (spostato) sembra più appropriato per le applicazioni Web in cui il client è un browser. I browser in genere seguono l'indirizzo reindirizzato nella risposta. Questo può essere utile per guidare l'utente ad una pagina di accesso.


La tua risposta:

401 Unauthorized soprattutto se non ti interessa o non stai reindirizzando le persone a una pagina di accesso

-o-

302 Found per implicare c'era la risorsa ma loro hanno bisogno di fornire credenziali per essere restituito a lui. Fatelo solo se userete un reindirizzamento e assicuratevi di fornire le informazioni appropriate nel corpo della risposta.

Altri suggerimenti:

401 Unauthorized viene generalmente utilizzato per le risorse a cui l'utente non ha accesso dopo aver gestito l'autenticazione.

403 Forbidden è un po 'oscuro per me in onestà. Lo uso quando blocco le risorse dal livello di file system e, come il tuo post ha detto, "l'autorizzazione non aiuta".

400 Bad Request è inappropriata in quanto la necessità di accedere non rappresenta una sintassi errata.


Chiedete "il migliore", "il modo giusto" e "il giusto", a turno, il che rende difficile rispondere a questa domanda perché quei criteri non sono necessariamente intercambiabili e possono, di fatto, entrare in conflitto - specialmente quando si tratta di RESTfulness .

La risposta "migliore" dipende dalla tua applicazione. Stai costruendo un'applicazione web POBB (Plain Old Browser-Based)? Stai creando un client nativo (ad esempio iOS o Android) e stai utilizzando un servizio sul Web? Stai facendo un uso pesante di AJAX per guidare gli aggiornamenti delle pagine web? Arricciare il cliente previsto?

Supponiamo che tu stia costruendo un'applicazione web tradizionale. Diamo un'occhiata a come lo fa Google (output ridotto per brevità):

$ curl -v http://gmail.com/
< HTTP/1.1 301 Moved Permanently
< Location: http://mail.google.com/mail/
< Content-Type: text/html; charset=UTF-8
< Content-Length: 225
< ...

Google innanzitutto ci reindirizza all'URL "vero" per GMail (utilizzando un reindirizzamento 302).

$ curl -v http://mail.google.com/mail/
< HTTP/1.1 302 Moved Temporarily
< Location: https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=http://mail.google.com/mail/&scc=1&ltmpl=default&ltmplcache=2
< Content-Type: text/html; charset=UTF-8
< Content-Length: 352
< ...

E poi ci reindirizza alla pagina di accesso (usando un reindirizzamento 302).

$ curl -v 'https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=http://mail.google.com/mail/&scc=1&ltmpl=default&ltmplcache=2'
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< ...

La stessa pagina di accesso viene consegnata con il codice di stato 200 !

Perché in questo modo?

Dal punto di vista dell'esperienza utente, se un utente accede a una pagina che non può visualizzare perché non è autenticato, si desidera portare l'utente a una pagina che consenta loro di correggerlo (tramite l'accesso). In questo esempio, la pagina di accesso è isolata ed è solo un'altra pagina (motivo per cui 200 è appropriato).

Potresti aprire una pagina 4XX con una spiegazione e un link alla pagina di accesso. Potrebbe, infatti, sembrare più riposante. Ma è un'esperienza utente peggiore.

Ok, ma c'è un caso in cui qualcosa come 403 ha un senso? Assolutamente.

Innanzitutto, tuttavia, notare che 403 non è ben definito nelle specifiche. Per capire come dovrebbe essere usato, devi vedere come è implementato sul campo.

403 è comunemente usato dai server web come Apache e IIS come codice di stato per le pagine restituite quando il browser richiede una lista di directory (un URI che termina con "/") ma il server ha elenchi di directory disabilitati. In questo caso, il 403 è davvero un 404 specializzato, e non c'è molto che tu possa fare per l'utente se non fargli sapere cosa è andato storto.

Tuttavia, ecco un esempio di un sito che utilizza il 403 per segnalare all'utente che non ha privilegi sufficienti e quali azioni intraprendere per correggere la situazione (controlla la risposta completa per i dettagli):

curl -v http://www.w3.org/Protocols/rfc2616/
< HTTP/1.1 403 Forbidden
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 1564
< ...

(Come nota a parte, 403 è anche presente nelle API basate sul Web, come l'API di Twitter, qui 403 significa "La richiesta è capita, ma è stata rifiutata. Un messaggio di errore di accompagnamento spiegherà il perché. negato a causa di limiti di aggiornamento. ")

Come miglioramento, supponiamo, tuttavia, che non si voglia reindirizzare l'utente a una pagina di accesso o forzare l'utente a seguire un collegamento alla pagina di accesso. Invece, si desidera visualizzare il modulo di accesso sulla pagina che l'utente non può vedere. Se si autenticano correttamente, vedono il contenuto quando la pagina viene ricaricata; se falliscono, ricevono di nuovo il modulo di accesso. Non navigano mai verso un altro URL.

In questo caso, un codice di stato 403 ha molto senso ed è omologato al caso 401, con l'avvertenza che il browser non visualizzerà una finestra di dialogo che chiede all'utente di autenticarsi - il modulo si trova nella pagina stessa .

Questo approccio all'autenticazione non è comune, ma potrebbe avere senso ed è preferibile a IMHO per le soluzioni pop-up-a-javascript-modal-to-log-in che gli sviluppatori cercano di implementare.

Si riduce alla domanda, vuoi reindirizzare o no?

Ulteriori: pensieri sul codice di stato 401 ...

Il codice di stato 401 - e l'autenticazione di base / digest associata - ha molte cose da fare per questo. È abbracciato dalle specifiche HTTP, è supportato da tutti i principali browser, non è intrinsecamente non-RESTful ... Il problema è che, dal punto di vista dell'esperienza utente, è molto poco attraente. C'è la finestra di dialogo pop-up non stilabile, criptica, la mancanza di una soluzione elegante per la disconnessione, ecc. Se tu (oi tuoi stakeholder / clienti) puoi vivere con questi problemi (un grande se), allora potrebbe essere definito come "corretto" "soluzione.


Non sto parlando di autenticazione HTTP qui, quindi questo è almeno un codice di stato che non useremo (401 Non autorizzato).

Sbagliato. 401 fa parte di Hypertext Transfer Protocol (RFC 2616 Fielding, et al.), Ma non limitato all'autenticazione HTTP. Inoltre, è l'unico codice di stato che indica che la richiesta richiede l'autenticazione dell'utente.

È possibile utilizzare i codici 302 e 200 ed è più semplice da implementare in alcuni scenari, ma non tutti. E se vuoi obbedire alle specifiche, 401 è l'unica risposta corretta che c'è.

E il 403 è davvero il codice più sbagliato da restituire. Come hai correttamente affermato ...

L'autorizzazione non aiuterà e la richiesta NON DEVE essere ripetuta.

Quindi questo chiaramente non è adatto per indicare che l'autorizzazione è un'opzione.

Vorrei attenermi allo standard: 401 Non autorizzato

-

AGGIORNARE

Per aggiungere un po 'più di informazioni, sollevando la confusione relativa a ...

La risposta DEVE includere un campo di intestazione Autenticato WWW (sezione 14.47) contenente una sfida applicabile alla risorsa richiesta.

Se pensi che ti impedirà di usare un 401, devi ricordare che c'è di più:

"Il valore del campo consiste di almeno una sfida che indica lo / i schema / i di autenticazione e i parametri applicabili all'URI della richiesta."

Questo "che indica il / i schema / i di autenticazione" significa che puoi optare per altri schemi di autenticazione!

Il protocollo HTTP (RFC 2616) definisce una struttura semplice per gli schemi di autenticazione di accesso, ma non è necessario utilizzare QUESTO framework.

In altre parole: non sei legato alla solita Autenticazione WWW. Devi solo indicare COME la tua webapp fa la sua autorizzazione e offrire i dati corrispondenti nell'intestazione, tutto qui. Secondo le specifiche, usando un 401, puoi scegliere il tuo veleno di autorizzazione! Ed è qui che la tua "webapp" può fare ciò che vuoi che faccia quando si tratta dell'intestazione 401 e della tua implementazione dell'autorizzazione.

Non lasciare che le specifiche ti confondano, pensando di dover utilizzare il solito schema di autenticazione HTTP. Tu no! L'unica cosa che le specifiche fanno davvero rispettare: devi solo / DEVE identificare lo schema di autenticazione del tuo webapp e passare i relativi parametri per consentire alla parte richiedente di avviare potenziali tentativi di autorizzazione.

E se non sei ancora sicuro, posso mettere tutto questo in una prospettiva semplice ma comprensibile: supponiamo che domani inventerai un nuovo schema di autorizzazione, quindi le specifiche ti permetteranno di usarlo anche tu. Se le specifiche avessero limitato l'implementazione di tali più recenti implementazioni della tecnologia di autorizzazione, tali specifiche sarebbero state modificate secoli fa. Le specifiche definiscono gli standard, ma in realtà non limitano la moltitudine di potenziali implementazioni.


Credo che 401 sia il codice di stato corretto per tornare dall'autorizzazione fallita. Riferimento RFC 2616 sezione 14.8 Si legge "Un agente utente che desidera autenticarsi con un server-- di solito, ma non necessariamente, dopo aver ricevuto una risposta 401 "





http-status-codes