Mã trạng thái HTTP chính xác khi chuyển hướng đến trang đăng nhập là gì?


132

Khi người dùng chưa đăng nhập và cố gắng truy cập một trang yêu cầu đăng nhập, mã trạng thái HTTP chính xác để chuyển hướng đến trang đăng nhập là gì?

Tôi đang hỏi vì không có mã phản hồi 3xx nào được W3C đặt ra có vẻ phù hợp với yêu cầu:

10.3.1 300 Nhiều lựa chọn

Tài nguyên được yêu cầu tương ứng với bất kỳ một trong các nhóm đại diện nào, mỗi đại diện có vị trí cụ thể của riêng nó và thông tin đàm phán do tác nhân điều khiển (phần 12) đang được cung cấp để người dùng (hoặc tác nhân người dùng) có thể chọn đại diện ưa thích và chuyển hướng yêu cầu đến vị trí đó.

Trừ khi đó là yêu cầu CHÍNH, phản hồi NÊN bao gồm một thực thể chứa danh sách các đặc điểm và vị trí tài nguyên mà từ đó người dùng hoặc tác nhân người dùng có thể chọn một thực thể phù hợp nhất. Định dạng thực thể được chỉ định bởi loại phương tiện được cung cấp trong trường tiêu đề Kiểu nội dung. Tùy thuộc vào định dạng và khả năng của

tác nhân người dùng, lựa chọn của sự lựa chọn phù hợp nhất CÓ THỂ được thực hiện tự động. Tuy nhiên, đặc điểm kỹ thuật này không xác định bất kỳ tiêu chuẩn cho lựa chọn tự động như vậy.

Nếu máy chủ có lựa chọn đại diện ưa thích, thì NÊN bao gồm URI cụ thể cho đại diện đó trong trường Vị trí; tác nhân người dùng CÓ THỂ sử dụng giá trị trường Vị trí để chuyển hướng tự động. Phản hồi này là bộ nhớ cache trừ khi có chỉ định khác.

10.3.2 301 Đã di chuyển vĩnh viễn

Tài nguyên được yêu cầu đã được gán một URI vĩnh viễn mới và mọi tham chiếu trong tương lai cho tài nguyên này NÊN sử dụng một trong các URI được trả về. Các máy khách có khả năng chỉnh sửa liên kết phải tự động liên kết lại các tham chiếu đến URI yêu cầu tới một hoặc nhiều tham chiếu mới được máy chủ trả về, nếu có thể. Phản hồi này là bộ nhớ cache trừ khi có chỉ định khác.

URI vĩnh viễn mới NÊN được cung cấp bởi trường Vị trí trong phản hồi. Trừ khi phương thức yêu cầu là CHÍNH, thực thể của phản hồi NÊN chứa một ghi chú siêu văn bản ngắn có siêu liên kết đến (các) URI mới.

Nếu mã trạng thái 301 được nhận để đáp ứng yêu cầu khác với GET hoặc HEAD, tác nhân người dùng KHÔNG ĐƯỢC tự động chuyển hướng yêu cầu trừ khi người dùng có thể xác nhận, vì điều này có thể thay đổi các điều kiện theo đó yêu cầu được đưa ra.

  Note: When automatically redirecting a POST request after
  receiving a 301 status code, some existing HTTP/1.0 user agents
  will erroneously change it into a GET request.

10.3.3 302 Tìm thấy

Tài nguyên được yêu cầu tạm thời nằm trong một URI khác. Do việc chuyển hướng có thể bị thay đổi, thỉnh thoảng, khách hàng NÊN tiếp tục sử dụng URI yêu cầu cho các yêu cầu trong tương lai. Phản hồi này chỉ có thể lưu trong bộ nhớ cache nếu được chỉ định bởi trường tiêu đề Cache-Control hoặc Hết hạn.

URI tạm thời NÊN được đưa ra bởi trường Vị trí trong phản hồi. Trừ khi phương thức yêu cầu là CHÍNH, thực thể của phản hồi NÊN chứa một ghi chú siêu văn bản ngắn có siêu liên kết đến (các) URI mới.

Nếu mã trạng thái 302 được nhận để đáp ứng yêu cầu không phải là GET hoặc HEAD, tác nhân người dùng KHÔNG được tự động chuyển hướng yêu cầu trừ khi người dùng có thể xác nhận, vì điều này có thể thay đổi các điều kiện theo đó yêu cầu được đưa ra.

  Note: RFC 1945 and RFC 2068 specify that the client is not allowed
  to change the method on the redirected request.  However, most
  existing user agent implementations treat 302 as if it

là một phản hồi 303, thực hiện GET trên giá trị trường Vị trí bất kể phương thức yêu cầu ban đầu. Các mã trạng thái 303 và 307 đã được thêm vào cho các máy chủ muốn làm rõ ràng rõ ràng loại phản ứng nào được mong đợi của khách hàng.

10.3.4 303 Xem Khác

Có thể tìm thấy phản hồi cho yêu cầu theo một URI khác và NÊN được truy xuất bằng phương thức GET trên tài nguyên đó. Phương thức này tồn tại chủ yếu để cho phép đầu ra của tập lệnh được kích hoạt POST để chuyển hướng tác nhân người dùng đến tài nguyên đã chọn. URI mới không phải là tài liệu tham khảo thay thế cho tài nguyên được yêu cầu ban đầu. Phản hồi 303 PHẢI KHÔNG được lưu trong bộ nhớ cache, nhưng phản hồi cho yêu cầu thứ hai (được chuyển hướng) có thể được lưu trong bộ nhớ cache.

URI khác nhau NÊN được đưa ra bởi trường Vị trí trong phản hồi. Trừ khi phương thức yêu cầu là CHÍNH, thực thể của phản hồi NÊN chứa một ghi chú siêu văn bản ngắn có siêu liên kết đến (các) URI mới.

  Note: Many pre-HTTP/1.1 user agents do not understand the 303
  status. When interoperability with such clients is a concern, the
  302 status code may be used instead, since most user agents react
  to a 302 response as described here for 303.

10.3.5 304 Không được sửa đổi

Nếu khách hàng đã thực hiện yêu cầu GET có điều kiện và quyền truy cập được cho phép, nhưng tài liệu chưa được sửa đổi, máy chủ NÊN trả lời với mã trạng thái này. Phản hồi 304 PHẢI KHÔNG chứa phần thân thông điệp và do đó luôn bị chấm dứt bởi dòng trống đầu tiên sau các trường tiêu đề.

Phản hồi PHẢI bao gồm các trường tiêu đề sau:

  - Date, unless its omission is required by section 14.18.1 If a

Máy chủ nguồn gốc không có đồng hồ tuân theo các quy tắc này và proxy và máy khách thêm Ngày của riêng họ vào bất kỳ phản hồi nào nhận được mà không cần một (như đã được chỉ định bởi [RFC 2068], phần 14.19), bộ đệm sẽ hoạt động chính xác.

  - ETag and/or Content-Location, if the header would have been sent
    in a 200 response to the same request
  - Expires, Cache-Control, and/or Vary, if the field-value might
    differ from that sent in any previous response for the same
    variant If the conditional GET used a strong cache validator (see

phần 13.3.3), phản hồi KHÔNG NÊN bao gồm các tiêu đề thực thể khác. Mặt khác (nghĩa là GET có điều kiện sử dụng trình xác nhận yếu), phản hồi KHÔNG PHẢI bao gồm các tiêu đề thực thể khác; điều này ngăn ngừa sự không nhất quán giữa các thực thể được lưu trữ và các tiêu đề được cập nhật.

Nếu một phản hồi 304 chỉ ra một thực thể hiện không được lưu trong bộ đệm, thì bộ đệm PHẢI bỏ qua phản hồi và lặp lại yêu cầu mà không có điều kiện.

Nếu bộ đệm sử dụng phản hồi 304 nhận được để cập nhật mục nhập bộ đệm, bộ đệm PHẢI cập nhật mục nhập để phản ánh bất kỳ giá trị trường mới nào được đưa ra trong phản hồi.

10.3.6 305 Sử dụng Proxy

Tài nguyên được yêu cầu PHẢI được truy cập thông qua proxy được cung cấp bởi trường Vị trí. Trường Vị trí cung cấp URI của proxy. Người nhận dự kiến ​​sẽ lặp lại yêu cầu này thông qua proxy. 305 phản hồi PHẢI chỉ được tạo bởi các máy chủ gốc.

  Note: RFC 2068 was not clear that 305 was intended to redirect a
  single request, and to be generated by origin servers only.  Not
  observing these limitations has significant security consequences.

10.3.7 306 (Không sử dụng)

Mã trạng thái 306 đã được sử dụng trong phiên bản trước của thông số kỹ thuật, không còn được sử dụng và mã được bảo lưu.

10.3.8 307 Chuyển hướng tạm thời

Tài nguyên được yêu cầu tạm thời nằm trong một URI khác. Do việc chuyển hướng có thể bị thay đổi trong dịp này, khách hàng NÊN tiếp tục sử dụng URI yêu cầu cho các yêu cầu trong tương lai. Phản hồi này chỉ có thể lưu trong bộ nhớ cache nếu được chỉ định bởi trường tiêu đề Cache-Control hoặc Hết hạn.

URI tạm thời NÊN được đưa ra bởi trường Vị trí trong phản hồi. Trừ khi phương thức yêu cầu là CHÍNH, thực thể của phản hồi NÊN chứa một ghi chú siêu văn bản ngắn có siêu liên kết đến (các) URI mới, vì nhiều tác nhân người dùng tiền HTTP / 1.1 không hiểu trạng thái 307. Do đó, lưu ý NÊN chứa thông tin cần thiết để người dùng lặp lại yêu cầu ban đầu trên URI mới.

Nếu mã trạng thái 307 được nhận để đáp ứng yêu cầu khác với GET hoặc HEAD, tác nhân người dùng KHÔNG được tự động chuyển hướng yêu cầu trừ khi người dùng có thể xác nhận, vì điều này có thể thay đổi các điều kiện theo đó yêu cầu được đưa ra.

Tôi đang sử dụng 302 cho bây giờ, cho đến khi tôi tìm thấy những câu trả lời đúng.

Cập nhật & kết luận:

HTTP 302 tốt hơn vì được biết là có khả năng tương thích tốt nhất với máy khách / trình duyệt.


1
Tôi sẽ nói hoàn toàn theo cách cuốn sách sẽ là trả lại một trang 401 và trang đăng nhập mà không cần chuyển hướng, nhưng tôi không chắc lựa chọn của bạn là gì.
Nick Craver

1
@Nick điểm tốt, nhưng tôi sẽ sợ tác dụng phụ từ đó nếu tôi đang xây dựng một hệ thống đăng nhập cổ điển.
Pekka

1
Tài khoản Ít nhất là trong kinh nghiệm của tôi.
Nick Craver

@Nick Với 401 "Phản hồi PHẢI bao gồm trường tiêu đề WWW-xác thực" - Làm cách nào tôi có thể kết hợp điều này với cơ sở dữ liệu MySQL? Không phải AuthType Basic và Digest bị giới hạn ở các tệp cấu hình apache như .htpassword, v.v ...?
Vidar Vestnes

Tôi muốn có một trang đăng nhập tùy chỉnh, không phải hộp thoại trình duyệt cơ bản yêu cầu tên người dùng và mật khẩu ...
Vidar Vestnes

Câu trả lời:


66

Tôi muốn nói rằng 303 thấy 302 khác được tìm thấy:

Tài nguyên được yêu cầu tạm thời nằm trong một URI khác. Do việc chuyển hướng có thể bị thay đổi , thỉnh thoảng , khách hàng NÊN tiếp tục sử dụng URI yêu cầu cho các yêu cầu trong tương lai. Phản hồi này chỉ có thể lưu trong bộ nhớ cache nếu được chỉ định bởi trường tiêu đề Cache-Control hoặc Hết hạn.

Theo ý kiến ​​của tôi, phù hợp nhất với một trang đăng nhập. Tôi ban đầu xem xét 303 see othermà sẽ làm việc như là tốt. Sau một số suy nghĩ, tôi muốn nói 302 Foundlà phù hợp hơn vì tài nguyên được yêu cầu đã được tìm thấy, chỉ có một trang khác để đi qua trước khi có thể truy cập được. Phản hồi không được lưu trong bộ nhớ cache theo mặc định cũng tốt.


4
Tôi đồng ý, nhưng tôi nghĩ 302 Found chỉ ra rằng tài nguyên đã được tìm thấy, ngay dưới một url khác. Ví dụ. Tôi muốn se / my-message / máy chủ trả lời bằng 302 vì "hôm nay" tin nhắn của tôi nằm ở "/ login /" (thay vì "/ message /") ... Tôi sử dụng 302, nhưng tôi không cảm thấy bối cảnh phù hợp 100%. Vì trang đăng nhập là một tài nguyên khác và không có cùng nội dung như được yêu cầu.
Vidar Vestnes

2
@PHP_Jedi đúng. 303 có thể phù hợp hơn từ quan điểm đó. Tuy nhiên, 302 đáng tin cậy hơn về khả năng tương thích của khách hàng.
Pekka

1
Đúng, tôi nghĩ rằng 303 có thể phù hợp với bối cảnh hơn vì nó nói "Phản hồi cho yêu cầu có thể được tìm thấy trong một URI khác". Điều này cho tôi biết rằng đó không phải là tài nguyên được tìm thấy trong một URI khác, mà chỉ là phản hồi cho yêu cầu này.
Vidar Vestnes

3
@PHP_Jedi Tôi không chắc liệu có đáng để dành nhiều thời gian cho việc này không. Cả máy khách và máy chủ trong thế giới http đều phải cực kỳ tự do và không có lỗi, vì vậy sẽ không có sự khác biệt thực sự nào cho dù bạn sử dụng 302hay 303, ngoại trừ điều đó 302được biết đến nhiều hơn. Tôi thấy mức độ chi tiết đáng khen ngợi và luôn luôn tốt để làm mọi thứ đúng, nhưng quá nhiều nỗ lực có thể là vô ích trong lĩnh vực cụ thể này.
Pekka

27
FYI: Google phát hành 302s
David Murdoch

51

Đây là một sự lạm dụng của cơ chế chuyển hướng HTTP. Nếu người dùng không được ủy quyền thì ứng dụng của bạn phải quay lại 401 Unauthorized. Trong trường hợp người dùng được ủy quyền nhưng không có quyền truy cập vào tài nguyên được yêu cầu thì 403 Forbiddenphải trả lại.

Bạn nên thực hiện chuyển hướng ở phía máy khách, ví dụ như bằng javascript. mã trạng thái để chuyển hướng vì ủy quyền bắt buộc không tồn tại . Sử dụng 30x cho việc này không phù hợp với HTTP.

Cách nghĩ về mã trạng thái HTTP của Mark Nottingham

401 Kích hoạt trái phép cơ chế xác thực yêu cầu của HTTP.

401 Unauthorizedmã trạng thái yêu cầu sự hiện diện của WWW-Authenticatetiêu đề hỗ trợ các loại xác thực khác nhau:

WWW-Xác thực: <type> realm = <realm>

Bearer, OAuth, Basic, Digest, Cookie, v.v.


20
Một số 401 có thể không phù hợp trong một số trường hợp như A server generating a 401 (Unauthorized) response MUST send a WWW-Authenticate header field( RFC ) và không phải tất cả các hệ thống đăng nhập đều sử dụng tiêu đề đó.
starbeamrainbowlabs

6
Giả sử bạn đang làm mới một trang được bảo vệ; javascript phía máy khách sẽ không có bất kỳ thay đổi nào để được gọi và trình duyệt sẽ bật cửa sổ đăng nhập thay vì chuyển hướng người dùng về phía trang đăng nhập - vì vậy cách duy nhất là sử dụng mã 30x.
Claude Brisson

2
Golang không thể sử dụng 401 để chuyển hướng. Điều đó có nghĩa là chúng ta nên sử dụng 30 * cho các chuyển hướng.
EIMEI

4
@EIMEI theo lý luận của bạn, nếu một ngôn ngữ hoặc thư viện khác buộc bạn phải sử dụng 401, thì Internet sẽ bị tiêu diệt. Quan điểm của tôi là: những gì bạn nói chỉ ra một vấn đề với Golang (mặc dù tôi thấy ngạc nhiên rằng nó sẽ có một thiết kế như vậy để không thể gửi 401s!)
Greg

2
@starbeamrainbowlabs Có một bản nháp cho Xác thực HTTP dựa trên Cookie dưới dạng tùy chọn trong tiêu đề WWW-xác thực. Xem: tools.ietf.org/html/draft-broyer-http-cookie-auth-00
aef

12

Tôi nghĩ rằng giải pháp thích hợp là tiêu đề HTTP 401 (Không được ủy quyền).

http://en.wikipedia.org/wiki/HTTP_codes#4xx_Client_Error

Mục đích của tiêu đề này là chính xác này. Nhưng, thay vì chuyển hướng đến một trang đăng nhập, quy trình chính xác sẽ là một cái gì đó như:

  • Người dùng không đăng nhập cố gắng truy cập một trang bị hạn chế đăng nhập.
  • hệ thống xác định người dùng chưa đăng nhập
  • hệ thống trả về tiêu đề HTTP 401 và hiển thị biểu mẫu đăng nhập trong cùng một phản hồi (không phải là chuyển hướng).

Đây là một cách thực hành tốt, như cung cấp một trang 404 hữu ích, với các liên kết sơ đồ trang web và một hình thức tìm kiếm chẳng hạn.

Hẹn gặp lại


20
RFC tuyên bố: "Phản hồi PHẢI bao gồm trường tiêu đề WWW-xác thực (phần 14.46) có chứa một thách thức áp dụng cho tài nguyên được yêu cầu." Phản hồi 401 thực sự chỉ có thể áp dụng khi sử dụng sơ đồ xác thực HTTP.
bshacklett

4
Trong trường hợp đó 403 sẽ tốt hơn vì nó nói rằng quyền truy cập chỉ bị cấm và tiêu đề ủy quyền sẽ không giúp đỡ
olanod

@bshacklett WWW-Authenticicate có thể được sử dụng cùng với nhiều sơ đồ xác thực (ví dụ Bearer, OAuth). Xem developer.mozilla.org/en-US/docs/Web/HTTP/Headers/...iana.org/assignments/http-authschemes/http-authschemes.xhtml
filip26

Có một bản nháp cho Xác thực HTTP dựa trên Cookie dưới dạng tùy chọn trong tiêu đề Xác thực WWW. Xem: tools.ietf.org/html/draft-broyer-http-cookie-auth-00
aef
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.