2015-04-07 38 views
10

Chciałbym wysłać kod odpowiedzi 401, jeśli żądający użytkownik nie jest uwierzytelniony, ale chciałbym również przekierować, gdy żądanie było HTML żądanie. Stwierdziłem, że Express 4 na to nie pozwala:Chains Express.js 4 res.status (401) do przekierowania

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

Czy ktoś wie, jak sobie z tym poradzić? To może nie być ograniczenie Expressu, ponieważ proszę o przekazanie dwóch nagłówków, ale nie rozumiem, dlaczego tak powinno być. Powinienem być w stanie przekazać odpowiedź "nieuwierzytelnioną" i przekierować użytkownika za jednym razem.

+0

Zauważyłem również przekierowania ekspresowe POST do GET, co mnie zaskoczyło. – Plato

+2

Krótka uwaga: jeśli do zasobu można uzyskać dostęp za pomocą uwierzytelnienia, kod statusu powinien wynosić 401. Jeśli jest całkowicie zabronione z uwierzytelnieniem lub bez niego, kod statusu powinien be 403. –

+1

@brockangelo Odpowiedź Ixe jest jedynym sposobem, w jaki wiem, jak to zrobić (ręcznie .set(), następnie .send()). Ale myślę, że większe pytanie brzmi: czy naprawdę chcesz wysłać 401, jeśli planujesz przekierowanie. Spójrz na link SO w moim komentarzu do odpowiedzi Jasona –

Odpowiedz

12

Istnieją pewne subtelne diferences z metodami odesłanie nowy nagłówek lokalizacji.

Z 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 

Z status i 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 

z oryginalnym (błędnej) podejście z użyciem 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 

Tak wygląda redirect zrezygnuje z poprzednich kodów statusu i wyśle ​​wartość domyślną (chyba, że ​​określono to w wywołaniu metody). Ma to sens z powodu korzystania z oprogramowania pośredniego w Express. Jeśli jakiś globalny program pośredniczący wykonałby wstępne testy wszystkich żądań (takich jak sprawdzanie poprawnych nagłówków akceptacji itp.), Nie wiedziałby, aby przekierować żądanie. Jednak oprogramowanie pośredniczące do uwierzytelniania byłoby w stanie zastąpić poprzednie ustawienia, aby je poprawnie ustawić.

AKTUALIZACJA: Jak stwierdzono w poniższych komentarzach, nawet jeśli Express może wysłać kod statusu 4XX z nagłówkiem Lokalizacja, nie oznacza to, że jest to akceptowalna odpowiedź, aby klient żądania mógł zrozumieć zgodnie ze specyfikacją. W rzeczywistości większość zignoruje nagłówek Location, chyba że kod stanu ma wartość 3XX.

+0

, który odpowiada (częściowo). 'przekierowanie porzuci wszystkie poprzednie kody statusu i wyśle ​​wartość domyślną' - zanotuj [dokumenty tutaj] (http://expressjs.com/api.html#res.redirect) "Jeśli nie określisz statusu, kod statusu domyślnie "302" Znaleziono "". Pamiętaj jednak, że funkcja 'przekierowania' działa tylko w zakresie 300. jest tu poprzednie SO - http://stackoverflow.com/questions/21519094/why-doesnt-express-redirect-properly-when-i-edit-the-status-code –

+0

@JustinMaat Uzgodnione, że ogólne wykorzystanie to jest niepoprawne.401 powinien zostać odesłany do requestera, aby powiadomił go, że powinien ponownie zażądać za pomocą właściwej metody uwierzytelniania określonej w nagłówku ['WWW-Authenticate'] (http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error). Zwykle jest tokenem lub podstawowym uwierzytelnieniem. Moją odpowiedzią było pokazanie, że Express * może * to zrobić, ale nie, że jest to poprawne. Aktualizuję moją odpowiedź, aby to odzwierciedlić. –

3

Możesz na pewno wysłać nagłówekwraz ze swoją stroną 401, jednak nie jest to zalecane, a większość przeglądarek nie zastosuje się do niego, jak w przypadku rfc2616.

Jednym ze sposobów przezwyciężenia tego ma służyć <meta http-equiv="refresh" content="0; url=/login"> wraz ze swojej strony 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>`);