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

Vid*_*nes 123 redirect http http-status-codes

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

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

10.3.1 300多种选择

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

除非是HEAD请求,否则响应应该包括一个实体,其中包含资源特征和位置列表,用户或用户代理可以从中选择最合适的资源特征和位置.实体格式由Content-Type头字段中给出的媒体类型指定.取决于格式和功能

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

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

10.3.2 301永久移动

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

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

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

  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.
Run Code Online (Sandbox Code Playgroud)

10.3.3 302找到

请求的资源暂时驻留在不同的URI下.由于重定向有时可能会被更改,因此客户端应该继续使用Request-URI来处理将来的请求.如果由Cache-Control或Expires头字段指示,则此响应仅可缓存.

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

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

  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
Run Code Online (Sandbox Code Playgroud)

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

10.3.4 303见其他

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

不同的URI应该由响应中的Location字段给出.除非请求方法是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.
Run Code Online (Sandbox Code Playgroud)

10.3.5 304未修改

如果客户端已执行条件GET请求并允许访问,但文档尚未被修改,则服务器应该响应此状态代码.304响应必须不包含消息体,因此总是在头字段之后的第一个空行终止.

响应必须包括以下标头字段:

  - Date, unless its omission is required by section 14.18.1 If a
Run Code Online (Sandbox Code Playgroud)

无时钟源服务器遵守这些规则,代理和客户端将自己的日期添加到任何没有响应的响应中(如[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
Run Code Online (Sandbox Code Playgroud)

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

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

如果高速缓存使用接收的304响应来更新高速缓存条目,则高速缓存必须更新该条目以反映响应中给出的任何新字段值.

10.3.6 305使用代理

必须通过Location字段给出的代理访问所请求的资源.Location字段提供代理的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.
Run Code Online (Sandbox Code Playgroud)

10.3.7 306(未使用)

306状态代码用于规范的先前版本,不再使用,代码保留.

10.3.8 307临时重定向

请求的资源暂时驻留在不同的URI下.由于重定向有时可能会被更改,因此客户端应该继续使用Request-URI来处理将来的请求.如果由Cache-Control或Expires头字段指示,则此响应仅可缓存.

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

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

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

更新和结论:

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

Pek*_*ica 61

我会说303看到其他 302发现:

请求的资源暂时驻留在不同的URI下.由于重定向有时可能会被更改,因此客户端应该继续使用Request-URI来处理将来的请求.如果由Cache-Control或Expires头字段指示,则此响应仅可缓存.

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

  • 仅供参考:谷歌发行302s (24认同)
  • 我同意,但我认为302 Found表明资源已被发现,就在另一个网址下.防爆.我想se/my-messages /服务器回答302,因为"今天"我的消息位于"/ login /"(而不是"/ messages /")...我使用302,但我不觉得上下文是100%匹配.由于登录页面是不同的资源,并且没有与请求相同的内容. (4认同)
  • @PHP_Jedi我不确定是否值得花那么多时间.无论如何,http世界中的客户端和服务器都必须非常宽松和容错,所以使用"302"或"303"没有真正的区别,除了"302"更为人所知.我发现细节水平值得称赞,并且总是把事情做好,但在这个特定领域,过多的努力可能是徒劳的. (3认同)
  • @PHP_Jedi是的.从该观点来看,303可能更合适.但是,302在客户端兼容性方面更可靠. (2认同)
  • 是的,我认为 303 可能更适合上下文,因为它声明“可以在不同的 URI 下找到对请求的响应”。这告诉我,在另一个 URI 中找到的不是资源本身,而是对此请求的响应。 (2认同)

fil*_*p26 47

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

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

如何考虑Mark Nottingham的HTTP状态代码

401 Unauthorized触发HTTP的请求认证机制.

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

WWW-Authenticate:<type> realm = <realm>

持票人,OAuth,基本,摘要,Cookie等

  • 401在某些情况下可能不合适,因为"生成401(未授权)响应的服务器必须发送WWW-Authenticate头字段"([RFC](http://tools.ietf.org/html/rfc7235#section- 4.1)),并非所有登录系统都使用该标头. (20认同)
  • 假设您正在刷新受保护的页面; 客户端javascript将不会有任何更改被调用,浏览器将弹出登录窗口而不是将用户重定向到登录页面 - 所以唯一的方法是使用30x代码. (4认同)
  • @EIMEI按照你的推理,如果另一种语言或图书馆强迫你使用401,那么互联网将注定失败.我的观点是:你说的是Golang的一个问题(虽然我觉得它有这么一个设计让它无法发送401s令人惊讶!) (4认同)
  • Golang无法使用401进行重定向。这意味着我们应该使用30 *进行重定向。 (2认同)
  • @starbeamrainbowlabs在WWW-Authenticate标头中有一个基于Cookie的HTTP身份验证草案作为选项.请参阅:https://tools.ietf.org/html/draft-broyer-http-cookie-auth-00 (2认同)

Gle*_*son 20

这里有很多令人信服且矛盾的反应!如何选择?

决赛入围者:

302 找到

表示请求的资源已暂时移动到 Location 标头给出的 URL。浏览器重定向到此页面,但搜索引擎不会更新其资源链接。

该规范要求在执行重定向时不得更改方法(和主体),但并非所有用户代理都符合。因此,建议仅将 302 代码设置为 GET 或 HEAD 方法的响应,并使用 307 临时重定向,因为在这种情况下明确禁止方法更改。 https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302

模糊,可能有问题,也可能已经过时,但可以工作,特别是对于 GET 请求。

307 临时重定向

请求的资源已暂时移动到 Location 标头给出的 URL。

307和302唯一的区别是307保证重定向请求时方法和主体不会改变。对于 302,一些旧客户端错误地将方法更改为 GET:使用非 GET 方法和 302 的行为在 Web 上是不可预测的,而使用 307 的行为是可预测的。对于 GET 请求,它们的行为是相同的。 https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307

我最初的想法是,如果您的应用程序支持 HTTP 1.1+,这将是更新、更清晰的临时重定向方法。

401 未经授权

表示客户端请求尚未完成,因为它缺少所请求资源的有效身份验证凭据。

此状态代码与 HTTP WWW-Authenticate 响应标头一起发送,该标头包含有关客户端在提示用户输入身份验证凭据后如何再次请求资源的信息。

此状态代码类似于 403 Forbidden 状态代码,不同之处在于,在导致此状态代码的情况下,用户身份验证可以允许访问资源。

我同意这可能是正确的响应代码,表示“除非您登录”。但几乎每个 Web 应用程序都使用带有 Cookie 的 HTML 表单进行登录,并且此 HTTP 代码不允许“Cookie”作为身份验证方案: https ://developer.mozilla.org/en-US/docs/Web/HTTP/Headers /WWW-Authenticatehttps://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml

有一些人指出有人在 2009 年起草了一个“Cookie”方案:WWW-Authenticate Cookie https ://datatracker.ietf.org/doc/html/draft-broyer-http-cookie-auth-00 不知道为什么它没有成功。也许是因为这超出了 HTTP 的范围?

如果没有“Cookie”作为选项,我认为这不适合基于 HTML 和 Cookie 的身份验证。

民意调查

在缺乏不可否认的单一“正确”答案的情况下,我研究了一些行业领导者正在做的事情。

Google:302 重定向到登录页面

请求网址: https: //mail.google.com/mail/u/0/ ?tab=cm 请求方法:GET 状态代码:302

响应:内容类型:text/html;charset=UTF-8 位置: https://accounts.google.com/ServiceLogin?service=mail&passive=1209600&osid=1&continue=https://mail.google.com/mail/u/0/?tab%3Dcm&followup=https: //mail.google.com/mail/u/0/?tab%3Dcm&emr=1

Microsoft:302 重定向到登录页面

请求 URL: https: //outlook.live.com/mail/0/? authRedirect=true&state=0 请求方法:GET 状态代码:302

回复:位置: https: //outlook.live.com/owa/0/ ?state=1&redirectTo=aHR0cHM6Ly9vdXRsb29rLmxpdmUuY29tL21haWwvMC8

Facebook:302 重定向至登录页面

请求网址: https: //www.facebook.com/friends请求方法:GET 状态代码:302

响应:位置: https: //www.facebook.com/login.php? next=https%3A%2F%2Fwww.facebook.com%2Ffriends

Twitter:200 个带有插页式登录页面

请求 URL: https: //twitter.com/messages/请求方法:GET 状态代码:200(来自服务人员)

我:307:临时重定向

我已经使用它十多年了,从来没有遇到过问题。并不是建议其他人采用它,只是说它在每个主要浏览器中都像宣传的 302 替代品一样工作。研究这个答案后,我可以确信改用 302。

结论

302是事实上的重定向标准,除非您需要将一个 POST 重定向到另一个 POST,但我没有尝试过。

确实,我认为 POST 应该要么成功,要么彻底失败。POST 会导致服务器上的状态发生更改(例如将产品添加到库存中),并且您确实想知道更改是否已处理以及处理了多少次。重定向会引发您的更改在重定向之前是否被接受的问题。一旦您决定从不重定向 POST,则 302 和 307 是等效的。302 中的“bug”出现在不切实际的用例中。因此,307 根本不应该被创建。而且 302 更流行,因此可能得到最好的支持。

对所有临时重定向使用单个代码的好处是您不必担心重定向的原因。

200使用 JavaScript 抛出一个插页式登录页面是另一种选择,可能更适合单页 Web 应用程序。您请求了该页面,您获得了该页面,但您将被迫登录才能看到内容。


Dav*_*ave 12

I think the appropriate solution is the HTTP 401 (Not Authorized) header.

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

The purpose of this header is exactly this. But, instead of redirecting to a login page, the correct process would be something like:

  • User not logged try to access a login-restricted page.
  • system identifies user is not logged
  • system returns HTTP 401 header, AND display the login form in the same response (not a redirect).

这是一个很好的做法,例如提供有用的404页面,站点地图链接和搜索表单.

再见.

  • RFC规定:"响应必须包含WWW-Authenticate头字段(第14.46节),其中包含适用于所请求资源的质询." 401响应实际上仅适用于使用HTTP身份验证方案. (19认同)
  • 在那种情况下,403会更好,因为它声明只是禁止访问,授权头不会有帮助 (4认同)