重定向到登录页面时正确的HTTP状态代码是什么?


132

当用户未登录并尝试访问需要登录的页面时,重定向到登录页面的正确HTTP状态代码是什么?

我问是因为W3C 提出的3xx响应代码似乎都不符合要求:

10.3.1 300个多项选择

所请求的资源对应于一组表示中的任何一个,每个都有自己的特定位置,并且提供了代理驱动的协商信息(第12节),以便用户(或用户代理)可以选择首选表示并重定向其表示。请求到该位置。

除非它是HEAD请求,否则响应应包含一个实体,其中包含资源特征和位置的列表,用户或用户代理可以从中选择最合适的一个。实体格式由“内容类型”标头字段中提供的媒体类型指定。取决于格式和功能

用户代理,可以自动执行最合适的选择。但是,该规范没有为这种自动选择定义任何标准。

如果服务器具有首选的表示形式,则应在“位置”字段中包含该表示形式的特定URI;用户代理可以使用“位置”字段值进行自动重定向。除非另有说明,否则此响应是可缓存的。

10.3.2 301永久移动

所请求的资源已被分配了一个新的永久URI,对该资源的任何将来引用都应使用返回的URI之一。具有链接编辑功能的客户端应在可能的情况下自动将对Request-URI的引用重新链接到服务器返回的一个或多个新引用。除非另有说明,否则此响应是可缓存的。

新的永久URI应该由响应中的Location字段给出。除非请求方法是HEAD,否则响应的实体应该包含简短的超文本注释,并带有指向新URI的超链接。

如果响应GET或HEAD以外的请求而收到301状态码,则用户代理不得自动重定向请求,除非用户可以确认,因为这可能会更改发出请求的条件。

  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

所请求的资源临时位于其他URI下。由于重定向有时可能会更改,因此客户端应继续将Request-URI用于将来的请求。仅当由Cache-Control或Expires标头字段指示时,此响应才可缓存。

临时URI应该由响应中的Location字段给出。除非请求方法是HEAD,否则响应的实体应该包含简短的超文本注释,并带有指向新URI的超链接。

如果响应GET或HEAD以外的请求而收到302状态码,则用户代理不得自动重定向请求,除非用户可以确认,因为这可能会更改发出请求的条件。

  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

是303响应,无论原始请求方法如何,都对Location字段值执行GET。已为希望明确弄清客户端期望哪种反应的服务器添加了状态代码303和307。

10.3.4 303查看其他

可以在不同的URI下找到对请求的响应,并且应该使用该资源上的GET方法来检索该请求。存在此方法主要是为了允许POST激活的脚本的输出将用户代理重定向到选定的资源。新URI不能替代原始请求的资源。303响应一定不能被缓存,但是对第二个(重定向的)请求的响应可能是可缓存的。

响应中的Location字段应给出不同的URI。除非请求方法是HEAD,否则响应的实体应该包含简短的超文本注释,并带有指向新URI的超链接。

  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未修改

如果客户端已经执行了一个有条件的GET请求并且允许访问,但是文档没有被修改,则服务器应该用这个状态码来响应。304响应必须不包含消息正文,因此始终由标头字段之后的第一个空行终止。

响应必须包括以下头域:

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

无时钟源服务器遵循这些规则,并且代理和客户端将自己的日期添加到没有响应的任何响应中(如[RFC 2068]第14.19节所指定),缓存将正常运行。

  - 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

第13.3.3节),该响应不应包含其他实体标题。否则(即,条件GET使用弱验证器),响应中不得包含其他实体标头;这样可以防止缓存的实体与更新的标头之间的不一致。

如果304响应指示当前未缓存的实体,则缓存必须忽略响应,并在没有条件的情况下重复请求。

如果缓存使用收到的304响应来更新缓存条目,则缓存必须更新该条目以反映响应中给定的任何新字段值。

10.3.6 305使用代理

所请求的资源必须通过位置字段给出的代理访问。位置字段提供代理的URI。预计收件人将通过代理重复此单个请求。305个响应只能由原始服务器生成。

  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(未使用)

306状态代码在规范的先前版本中使用,不再使用,并且保留该代码。

10.3.8 307临时重定向

所请求的资源临时位于其他URI下。由于重定向有时可能会改变,客户端应该继续使用Request-URI来处理以后的请求。仅当由Cache-Control或Expires标头字段指示时,此响应才可缓存。

临时URI应该由响应中的Location字段给出。除非请求方法是HEAD,否则响应的实体应包含简短的超文本注释,并带有指向新URI的超链接,因为许多HTTP / 1.1之前的用户代理不了解307状态。因此,注释应该包含用户在新URI上重复原始请求所必需的信息。

如果响应GET或HEAD以外的请求而接收到307状态码,则用户代理不得自动重定向请求,除非用户可以确认,因为这可能会更改发出请求的条件。

我使用的是302,现在,直到我找到正确的答案。

更新和结论:

HTTP 302更好,因为它与客户端/浏览器具有最佳兼容性。


1
我要说的绝对是按书的方式返回没有重定向的401和登录页面,但是我不确定您的选择是什么。
尼克·克拉弗

1
@Nick好点,但是如果我构建经典的登录系统,我会担心会有副作用。
Pekka 2010年

1
@Pekka-绝对同意,这取决于它所处的平台以及如何完全处理所有内容,还包括Intranet与Internet之间的关系,我相信...您通常在Intranet上以不同的方式进行身份验证,至少以我的经验。
尼克·克拉弗

@Nick与401“响应必须包含WWW-Authenticate标头字段”-如何将其与MySQL数据库结合?AuthType Basic和Digest是否仅限于.htpassword等apache配置文件?
维达尔·韦斯特尼斯

我想要一个自定义的登录页面,而不是基本的浏览器对话框,要求用户名和密码...
Vidar Vestnes,2010年

Answers:


66

我想说303查看其他 302找到:

所请求的资源临时位于其他URI下。由于重定向有时可能会更改,因此客户端应继续将Request-URI用于将来的请求。仅当由Cache-Control或Expires标头字段指示时,此响应才可缓存。

我认为最适合登录页面。最初303 see other,我认为哪种方法也一样。经过一番思考,我会说302 Found更贴合,因为所请求的资源发现,那里只是另外一个页面要经过之前可以访问它。默认情况下,响应不会被缓存,这也很好。


4
我同意,但是我认为302 Found指示在另一个URL下找到了资源。例如 我想用/ 302 se / my-messages /服务器答复,因为“今天”我的消息位于“ / login /”(而不是“ / messages /”)...我使用302,但我不觉得上下文是100%匹配的。由于登录页面是不同的资源,并且具有与请求不同的内容。
维达尔·韦斯特尼斯

2
@PHP_Jedi是。从该观点来看,303可能更合适。但是,就客户端兼容性而言,302更可靠。
Pekka 2010年

1
是的,我认为303可能更适合上下文,因为它声明“可以在不同的URI下找到对请求的响应”。这是在告诉我,不是在另一个URI中找到资源本身,而是仅是对此请求的响应。
维达尔·韦斯特尼斯

3
@PHP_Jedi我不确定是否值得花那么多时间。无论如何,http世界中的客户端和服务器都必须极其自由且具有容错能力,因此,无论您使用302还是303,都没有真正的区别,除非302众所周知。我认为细节水平值得称赞,并且做好事情总是好事,但是在这个特定领域过多的努力可能是徒劳的。
Pekka 2010年

27
仅供参考:Google发行302s
David Murdoch

51

这是对HTTP重定向机制的滥用。如果未授权用户,则您的应用必须返回401 Unauthorized。如果用户被授权但无法访问所请求的资源,则403 Forbidden必须返回该用户。

您应该在客户端进行重定向,例如通过javascript。重定向的状态码,因为所需的授权不存在。为此使用30x不符合HTTP。

马克·诺丁汉(Mark Nottingham)如何思考HTTP状态代码

401未经授权会触发HTTP的请求身份验证机制。

401 Unauthorized状态码要求存在WWW-Authenticate支持各种身份验证类型的标头:

WWW验证:<type> realm = <realm>

承载,OAuth,基本,摘要,Cookie等


20
401在某些情况下可能不适合A server generating a 401 (Unauthorized) response MUST send a WWW-Authenticate header fieldRFC),并且并非所有登录系统都使用该标头。
starbeamrainbowlabs

6
假设您正在刷新受保护的页面;客户端javascript不会有任何更改,并且浏览器将弹出一个登录窗口,而不是将用户重定向到登录页面-因此,唯一的方法是使用30x代码。
克劳德·布里森

2
Golang无法使用401进行重定向。这意味着我们应该使用30 *进行重定向。
EIMEI '16

4
@EIMEI遵循您的推理,如果另一种语言或库迫使您使用401,那么互联网将注定要失败。我的观点是:您的言论指出了Golang的问题(尽管我感到惊讶的是,它的设计使其无法发送401!)
Greg

2
@starbeamrainbowlabs WWW-Authenticate标头中有一个基于Cookie的HTTP身份验证的草稿,作为一个选项。请参阅:tools.ietf.org/html/draft-broyer-http-cookie-auth-00
AEF

12

我认为合适的解决方案是HTTP 401(未授权)标头。

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

该头文件的目的正是这样。但是,除了重定向到登录页面之外,正确的过程类似于:

  • 未登录的用户尝试访问登录受限的页面。
  • 系统标识用户未登录
  • 系统返回HTTP 401标头,并以相同的响应(而非重定向)显示登录表单。

这是一个好习惯,例如提供有用的404页面,站点地图链接和搜索表单。

再见。


20
RFC声明:“响应必须包含一个WWW-Authenticate标头字段(第14.46节),其中包含适用于所请求资源的质询。” 401响应实际上仅在使用HTTP身份验证方案时适用。
bshacklett

4
在那种情况下403会更好,因为它声明完全禁止访问,并且授权标头将无济于事
olanod 2012年

@bshacklett WWW-Authenticate可以与许多身份验证方案(例如Bearer,OAuth)一起使用。请参阅developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…iana.org/assignments/http-authschemes/http-authschemes.xhtml
filip26 '18

WWW-Authenticate标头中有一个基于Cookie的HTTP身份验证草稿作为选项。请参阅:tools.ietf.org/html/draft-broyer-http-cookie-auth-00
AEF
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.