当用户未登录并尝试访问需要登录的页面时,重定向到登录页面的正确 HTTP 状态代码是什么?
我问是因为3xx response codes set out by the W3C 似乎 都不符合要求:
10.3.1 300 多项选择 请求的资源对应于一组表示中的任何一个,每个表示都有自己的特定位置,并且正在提供代理驱动的协商信息(第 12 节),以便用户(或用户代理)可以选择首选表示并将其请求重定向到该位置。除非它是一个 HEAD 请求,否则响应应该包含一个实体,该实体包含一个资源特征和位置列表,用户或用户代理可以从中选择最合适的一个。实体格式由 ContentType 标头字段中给出的媒体类型指定。根据用户代理的格式和能力,可以自动选择最合适的选项。但是,本规范没有为这种自动选择定义任何标准。如果服务器有首选的表示形式,它应该在 Location 字段中包含该表示形式的特定 URI;用户代理可以使用 Location 字段值进行自动重定向。除非另有说明,否则此响应是可缓存的。 10.3.2 301 Moved Permanently 请求的资源已经被分配了一个新的永久 URI,并且任何将来对该资源的引用都应该使用返回的 URI 之一。如果可能,具有链接编辑功能的客户端应该自动将对 Request-URI 的引用重新链接到服务器返回的一个或多个新引用。除非另有说明,否则此响应是可缓存的。新的永久 URI 应该由响应中的 Location 字段给出。除非请求方法是 HEAD,否则响应的实体应该包含一个简短的超文本注释,其中包含指向新 URI 的超链接。如果收到 301 状态代码以响应 GET 或 HEAD 以外的请求,用户代理不得自动重定向请求,除非用户可以确认,因为这可能会改变发出请求的条件。注意:当收到 301 状态码后自动重定向 POST 请求时,一些现有的 HTTP/1.0 用户代理会错误地将其更改为 GET 请求。 10.3.3 302 Found 请求的资源临时驻留在不同的 URI 下。由于重定向有时可能会改变,客户端应该继续使用 Request-URI 来处理未来的请求。此响应仅在由 Cache-Control 或 Expires 标头字段指示时才可缓存。临时 URI 应该由响应中的 Location 字段给出。除非请求方法是 HEAD,否则响应的实体应该包含一个简短的超文本注释,其中包含指向新 URI 的超链接。如果收到 302 状态码以响应 GET 或 HEAD 以外的请求,除非用户可以确认,否则用户代理不得自动重定向请求,因为这可能会改变发出请求的条件。注意:RFC 1945 和 RFC 2068 指定不允许客户端更改重定向请求的方法。然而,大多数现有的用户代理实现将 302 视为 303 响应,无论原始请求方法如何,都对 Location 字段值执行 GET。状态码 303 和 307 已被添加用于希望明确明确期望客户端做出何种反应的服务器。 10.3.4 303 See Other 可以在不同的 URI 下找到对请求的响应,并且应该在该资源上使用 GET 方法检索。此方法的存在主要是为了允许 POST 激活脚本的输出将用户代理重定向到选定的资源。新的 URI 不是原始请求资源的替代引用。 303 响应不能被缓存,但对第二个(重定向)请求的响应可能是可缓存的。不同的 URI 应该由响应中的 Location 字段给出。除非请求方法是 HEAD,否则响应的实体应该包含一个简短的超文本注释,其中包含指向新 URI 的超链接。注意:许多 HTTP/1.1 之前的用户代理不理解 303 状态。当考虑与此类客户端的互操作性时,可以使用 302 状态代码,因为大多数用户代理对 302 响应做出反应,如此处针对 303 所述。 10.3.5 304 Not Modified 如果客户端已执行条件 GET 请求和访问是允许的,但是文档没有被修改,服务器应该用这个状态码响应。 304 响应不能包含消息体,因此总是由头字段之后的第一个空行终止。响应必须包含以下标头字段: - 日期,除非第 14.18.1 节要求省略它 如果无时钟源服务器遵守这些规则,并且代理和客户端将自己的日期添加到没有收到的任何响应中(如已指定[RFC 2068],第 14.19 节),缓存将正确运行。 - ETag 和/或 Content-Location,如果标头将在对同一请求的 200 响应中发送 - Expires、Cache-Control 和/或 Vary,如果字段值可能与任何先前响应中发送的不同对于相同的变体如果条件 GET 使用了强缓存验证器(参见第 13.3.3 节),则响应不应包含其他实体标头。否则(即,条件 GET 使用弱验证器),响应不得包含其他实体标头;这可以防止缓存的实体主体和更新的标头之间的不一致。如果 304 响应指示当前未缓存的实体,则缓存必须忽略响应并在没有条件的情况下重复请求。如果缓存使用接收到的 304 响应来更新缓存条目,则缓存必须更新该条目以反映响应中给出的任何新字段值。 10.3.6 305 使用代理 请求的资源必须通过位置字段给出的代理访问。 Location 字段给出了代理的 URI。接收者应该通过代理重复这个单一的请求。 305 响应必须只能由源服务器生成。注意:RFC 2068 并不清楚 305 旨在重定向单个请求,并且仅由源服务器生成。不遵守这些限制会产生重大的安全后果。 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 更好,因为它与客户端/浏览器具有最佳兼容性。
我会说 303 看到其他 302 Found:
请求的资源临时驻留在不同的 URI 下。由于重定向有时可能会改变,客户端应该继续使用 Request-URI 来处理未来的请求。此响应仅在由 Cache-Control 或 Expires 标头字段指示时才可缓存。
我认为最适合登录页面。我最初认为 303 see other
也可以。经过一番思考,我会说 302 Found
更合适,因为找到了请求的资源,只有另一个页面要经过才能访问它。默认情况下,响应不会被缓存,这也很好。
这是对 HTTP 重定向机制的误用。如果用户未获得授权,那么您的应用必须返回 401 Unauthorized
。如果用户已获得授权但无权访问所请求的资源,则必须返回 403 Forbidden
。
您应该在客户端进行重定向,例如通过 javascript。重定向的状态码,因为所需的授权不存在。为此使用 30x 不符合 HTTP。
How to Think About HTTP Status Codes by Mark Nottingham
401 Unauthorized 触发 HTTP 的请求认证机制。
401 Unauthorized
状态代码需要存在支持各种身份验证类型的 WWW-Authenticate
标头:
WWW-Authenticate:
Bearer、OAuth、Basic、Digest、Cookie 等
超文本传输协议 (HTTP) 身份验证方案注册表
基于 Cookie 的 HTTP 身份验证 - DRAFT
A server generating a 401 (Unauthorized) response MUST send a WWW-Authenticate header field
(RFC),而且并非所有登录系统都使用该标头。
我认为适当的解决方案是 HTTP 401(未授权)标头。
http://en.wikipedia.org/wiki/HTTP_codes#4xx_Client_Error
此标头的目的正是如此。但是,正确的过程不是重定向到登录页面,而是如下所示:
未登录的用户尝试访问登录限制页面。
系统识别用户未登录
系统返回 HTTP 401 标头,并在同一响应中显示登录表单(不是重定向)。
这是一个很好的做法,例如提供有用的 404 页面、站点地图链接和搜索表单。
再见。
这里有很多令人信服和矛盾的回应!如何选择?
决赛选手:
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-Authenticate 和 https://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 的身份验证。
民意调查
在没有一个不可否认的单一“正确”答案的情况下,我查看了一些行业领导者正在做的事情。
谷歌:302重定向到登录页面
请求 URL:https://mail.google.com/mail/u/0/?tab=cm 请求方法:GET 状态码:302 响应:content-type: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/?状态=1&redirectTo=aHR0cHM6Ly9vdXRsb29rLmxpdmUuY29tL21haWwvMC8
Facebook:302 重定向到登录页面
请求 URL: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(来自 service worker)
我:307:临时重定向
我已经使用了十多年,从来没有遇到过问题。不建议其他人采用它,只是说它在每个主要浏览器中都像宣传的 302 替代方案一样工作。由于研究了这个答案,我可能会被说服改用 302。
结论
302 是重定向的事实标准,除非您需要将 POST 重定向到另一个 POST,但我没有尝试过。
真的,我认为 POST 要么成功,要么彻底失败。 POST 会导致服务器上的状态更改(例如将产品添加到库存),您真的想知道更改是否已处理以及处理了多少次。重定向会引发在重定向之前您的更改是否被接受的问题。一旦您决定从不重定向 POST,则 302 和 307 是等效的。 302 中的“错误”出现在不切实际的用例中。因此,永远不应该创建 307。 302 也更受欢迎,因此可能得到最好的支持。
对所有临时重定向使用单个代码的好处是您不必担心重定向的原因。
200 与 JavaScript 抛出一个插页式登录页面是另一种选择,可能更适合单页 web 应用程序。您请求了该页面,您获得了该页面,但您将被迫登录才能看到内容。
不定期副业成功案例分享
302
还是303
都没有真正的区别,只是302
更为人所知。我发现细节水平值得称赞,把事情做好总是好的,但在这个特定领域,太多的努力可能是徒劳的。