2015-04-07 22 views
10

Vorrei inviare un codice di risposta 401 se l'utente richiedente non è autenticato, ma vorrei anche reindirizzare quando la richiesta era un HTML richiesta. Ho trovato che Express 4 non consente questo:Chaining Express.js 4 res.status (401) a un reindirizzamento

res.status(401).redirect('/login') 

Qualcuno sa di un modo per gestire questo? Questo potrebbe non essere un limite di Express, dal momento che sto chiedendo di passare sostanzialmente due intestazioni, ma non vedo perché dovrebbe essere così. Dovrei essere in grado di passare una risposta "non autenticata" e reindirizzare l'utente tutto in una volta.

+0

Ho anche notato il reindirizzamento espresso POST to GET, che mi ha sorpreso – Plato

+2

Solo una breve nota: se l'asset può accedere con autenticazione il codice di stato dovrebbe essere 401. Se è completamente vietato con o senza autenticazione il codice di stato dovrebbe be 403. –

+1

@brockangelo La risposta di Ixe è l'unico modo in cui so come farlo (manualmente .set(), poi .send()). Ma penso che la domanda più grande sia se vuoi veramente mandare un 401 se stai pianificando un reindirizzamento. Dai un'occhiata al link SO nel mio commento alla risposta di Jason –

risposta

12

Ci sono alcuni diferences sottili con i metodi per l'invio di nuovo un nuovo header posizione.

Con redirect:

app.get('/foobar', function (req, res) { 
    res.redirect(401, '/foo'); 
}); 
// Responds with 
HTTP/1.1 401 Unauthorized 
X-Powered-By: Express 
Location: /foo 
Vary: Accept 
Content-Type: text/plain; charset=utf-8 
Content-Length: 33 
Date: Tue, 07 Apr 2015 01:25:17 GMT 
Connection: keep-alive 

Unauthorized. Redirecting to /foo 

Con status e location:

app.get('/foobar', function (req, res) { 
    res.status(401).location('/foo').end(); 
}); 
// Responds with 
HTTP/1.1 401 Unauthorized 
X-Powered-By: Express 
Location: /foo 
Date: Tue, 07 Apr 2015 01:30:45 GMT 
Connection: keep-alive 
Transfer-Encoding: chunked 

Con l'approccio originale (non corretta) utilizzando redirect:

app.get('/foobar', function (req, res) { 
    res.status(401).redirect('/foo')(); 
}); 
// Responds with 
HTTP/1.1 302 Moved Temporarily 
X-Powered-By: Express 
Location: /foo 
Vary: Accept 
Content-Type: text/plain; charset=utf-8 
Content-Length: 38 
Date: Tue, 07 Apr 2015 01:26:38 GMT 
Connection: keep-alive 

Moved Temporarily. Redirecting to /foo 

Quindi sembra che redirect abbandonerà eventuali codici di stato precedenti e invierà il valore predefinito (se non specificato nella chiamata al metodo). Questo ha senso a causa dell'uso del middleware all'interno di Express. Se avessi alcuni middleware globali che eseguono i pre-controlli su tutte le richieste (come il controllo delle intestazioni di accettazione corrette, ecc.) Non saprebbero reindirizzare una richiesta. Tuttavia, il middleware di autenticazione avrebbe e quindi avrebbe ignorato eventuali impostazioni precedenti per impostarle correttamente.

AGGIORNAMENTO: Come indicato nei commenti seguenti, anche se Express può inviare un codice di stato 4XX con un'intestazione di posizione non significa che sia una risposta accettabile per un client di richiesta da comprendere in base alle specifiche. In effetti la maggior parte ignorerà l'intestazione Location a meno che il codice di stato non sia un valore 3XX.

+0

questo risponde (parzialmente). 'reindirizzamento abbandonerà eventuali codici di stato precedenti e invierà il valore predefinito' - nota [docs qui] (http://expressjs.com/api.html#res.redirect) "Se non si specifica lo stato, il codice di stato il valore predefinito è "302" Trovato "". Nota comunque, penso che la funzione 'redirect' funzioni solo sulla gamma 300. c'è un SO precedente su questo qui - http://stackoverflow.com/questions/21519094/why-doesnt-express-redirect-properly-when-i-edit-the-status-code –

+0

@JustinMaat Concordato che l'uso complessivo di questo non è corretto401 deve essere restituito al richiedente per far sapere che deve richiedere di nuovo con il metodo di autenticazione corretto specificato tramite l'intestazione ['WWW-Authenticate'] (http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error). Questo è in genere un token o un'autenticazione di base. La mia risposta è stata dimostrare che Express * può * farlo ma non è corretto farlo. Aggiornamento della mia risposta per riflettere questo. –

3

È possibile inviare un'intestazione Location: /login insieme alla pagina 401, tuttavia ciò non è consigliabile e la maggior parte dei browser non la seguirà, come da rfc2616.

Un modo per farlo ovviare a questo, è quello di servire <meta http-equiv="refresh" content="0; url=/login"> a fianco con la tua pagina 401:

res.set('Content-Type', 'text/html'); 
res.status(401).send('<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=/login"></head></html>`);