2015-04-07 12 views
10

Tôi muốn gửi mã phản hồi 401 nếu người dùng yêu cầu không được xác thực, nhưng tôi cũng muốn chuyển hướng khi yêu cầu là HTML yêu cầu. Tôi đã tìm thấy Express 4 không cho phép điều này:Res.status Chaining Express.js 4 (401) để chuyển hướng

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

Có ai biết cách xử lý việc này không? Điều này có thể không phải là một hạn chế của Express, vì tôi yêu cầu về cơ bản vượt qua hai tiêu đề, nhưng tôi không thấy lý do tại sao phải như vậy. Tôi sẽ có thể chuyển một phản hồi "không được xác thực" và chuyển hướng tất cả người dùng trong một lần.

+0

Tôi cũng nhận thấy chuyển hướng nhanh POST tới GET, điều này làm tôi ngạc nhiên – Plato

+2

Chỉ cần lưu ý nhanh: nếu nội dung có thể truy cập có xác thực mã trạng thái phải là 401. Nếu hoàn toàn bị cấm hoặc không xác thực mã trạng thái 403. –

+1

@brockangelo Câu trả lời của Ixe là cách duy nhất tôi biết làm thế nào để làm điều này (bằng tay .set(), sau đó .send()). Nhưng tôi nghĩ câu hỏi lớn hơn là liệu bạn có thực sự muốn gửi 401 nếu bạn định chuyển hướng không. Hãy xem liên kết SO trong bình luận của tôi cho câu trả lời của Jason –

Trả lời

12

Có một số diferences tinh tế với các phương pháp để gửi lại một tiêu đề vị trí mới.

Với 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 

Với statuslocation:

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 

Với cách tiếp cận ban đầu (không chính xác) sử dụng 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 

Vì vậy, nó trông giống như redirect sẽ từ bỏ mọi mã trạng thái trước đó và gửi giá trị mặc định (trừ khi được chỉ định bên trong cuộc gọi phương thức). Điều này có ý nghĩa do việc sử dụng phần mềm trung gian trong Express. Nếu bạn có một số phần mềm trung gian toàn cầu thực hiện kiểm tra trước trên tất cả các yêu cầu (như kiểm tra các tiêu đề chấp nhận chính xác, v.v.), chúng sẽ không biết chuyển hướng yêu cầu. Tuy nhiên phần mềm trung gian xác thực sẽ và do đó nó sẽ biết ghi đè bất kỳ cài đặt trước nào để đặt chúng chính xác.

CẬP NHẬT: Như đã nêu trong các nhận xét bên dưới mặc dù Express có thể gửi mã trạng thái 4XX với tiêu đề Vị trí không có nghĩa là phản hồi có thể chấp nhận được cho ứng dụng khách yêu cầu. Trên thực tế, hầu hết sẽ bỏ qua tiêu đề Vị trí trừ khi mã trạng thái là giá trị 3XX.

+0

câu trả lời này (một phần). 'chuyển hướng sẽ từ bỏ bất kỳ mã trạng thái trước nào và gửi giá trị mặc định' - lưu ý [tài liệu ở đây] (http://expressjs.com/api.html#res.redirect) "Nếu bạn không chỉ định trạng thái, mã trạng thái mặc định là “302“ Đã tìm thấy ”. Tuy nhiên, lưu ý rằng, chức năng 'redirect' chỉ hoạt động trên phạm vi 300. có một SO trước đây về điều này ở đây - http://stackoverflow.com/questions/21519094/why-doesnt-express-redirect-properly-when-i-edit-the-status-code –

+0

@JustinMaat Đồng ý rằng việc sử dụng tổng thể Điều này là không chính xác.401 phải được gửi lại cho người yêu cầu để cho họ biết họ nên yêu cầu lại bằng phương pháp xác thực chính xác được chỉ định thông qua tiêu đề ['WWW-Authenticate'] (http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error). Đây thường là mã thông báo hoặc xác thực cơ bản. Câu trả lời của tôi là để cho thấy Express * có thể * làm điều đó nhưng không phải là nó là chính xác để làm như vậy. Cập nhật câu trả lời của tôi để phản ánh điều này. –

3

Bạn chắc chắn có thể gửi tiêu đề Location: /login cùng với trang 401 của mình, tuy nhiên, điều này không được thông báo và hầu hết các trình duyệt sẽ không theo dõi, theo rfc2616.

Một cách để làm khắc phục điều này, là để phục vụ <meta http-equiv="refresh" content="0; url=/login"> cùng với trang 401 của bạn:

res.set('Content-Type', 'text/html'); 
res.status(401).send('<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=/login"></head></html>`); 
Các vấn đề liên quan