【问题标题】:Is it possible to send a 401 Unauthorized AND redirect (with a Location)?是否可以发送 401 Unauthorized AND 重定向(带有位置)?
【发布时间】:2012-02-05 05:32:12
【问题描述】:

我想发送401 Unauthorized 并将客户端重定向到某个地方。然而:

如果我这样做:

header('HTTP/1.1 401 Unauthorized');
header('Location: /');

服务器发送302 FoundLocation,所以不是401 Unauthorized

如果我这样做:

header('Location: /');
header('HTTP/1.1 401 Unauthorized');

浏览器同时收到401 UnauthorizedLocation,但不重定向。

(IE 9 和 Chrome 16 的行为相同,所以我猜它是正确的)

也许我误用了 HTTP?我希望我的应用程序界面对所有客户端都完全相同:文本浏览器、现代浏览器、API 调用等。401 + 响应文本会告诉 API 用户什么是什么。重定向对浏览器很有用。

有(好的)方法吗?

【问题讨论】:

    标签: http-headers http-status-code-401 http-redirect


    【解决方案1】:

    根据定义(参见RFC 2616),HTTP 302 响应代码重定向代码。没有它,位置标头可能会被忽略。

    但是,您可以发送 HTTP 401 响应并仍然显示输出。无需将用户重定向到错误页面,您只需将要发送的内容写入同一请求的 HTTP 正文中即可。

    【讨论】:

    • 这很有道理,为什么要重定向?只需加载登录页面或其他内容,对吗?
    • 401页面中的登录表单……这其实是有道理的。为什么我没有想到!?
    • 这个答案实际上支持制作网页的模块化模板以包含在这些情况下的想法。
    • 我正在尝试使用 POST 数据注销 BASIC-AUTH。它工作正常,但您最终会在刷新问题时重新提交表单,这是您无法通过重定向解决的。您需要发送 401 来注销,但您还需要 302 来重定向。我不知道如何处理这个。
    • 没关系;解决了。在 401 页面的正文中发送了 Javascript 重定向。
    【解决方案2】:

    3xx 表示重定向
    4xx 表示浏览器出错了。

    代码按原样拆分是有原因的——它们不会混合;)

    【讨论】:

    • 为了扩展这一点——在 HTTP 中分离关注点的方式鼓励你不要创建不必要的重定向——你应该能够发送所有必要的信息(在这种情况下,你是未经授权的(标头)在单个响应中访问资源和有关如何验证自己(正文)的信息,而不是需要两个单独的事务。
    【解决方案3】:

    除了 Kolink 和 David (+1) 的精彩回答之外,我要指出的是,您正试图通过返回 401 并告诉浏览器重定向来更改 HTTP 协议的语义。这不是 HTTP 协议的预期工作方式,如果您确实找到了获得该结果的方法,HTTP 客户端会发现您的服务的行为是非标准的。

    要么发送 401 并允许浏览器处理它,要么以不同的方式处理这种情况(例如,正如一位评论者建议的那样,重定向到登录页面,或者可能重定向到解释用户无权访问的页面)。

    【讨论】:

    • 我很确定我们都不会像 70 年前那样按照最初预期的方式使用 HTTP。这根本不重要。
    • @Rudie 当人们必须通过 HTTP 相互通信时,双方遵循什么做法很重要,这就是标准很重要的原因。
    • @Alireza 双方遵循的做法确实很重要,但这种做法通常不是 HTTP 最初的预期。这很好。只是最近几年 REST 突然火了起来,“改变 HTTP 协议的语义”是“错误的”。
    • @Rudie 是的,我同意你的看法。我的观点完全局限于 REST。显然,当任何一方想要自定义 HTTP 语义时,只要任何其他方同意就可以了
    • @Rudie:浏览器实现了当前的 HTTP 标准。浏览器制造商并没有齐心协力决定以一致的方式忽略该标准。如果服务器应用程序的行为方式与标准相反,则不能期望浏览器会按照您希望的方式做出反应,或者它们会以一致的方式做出反应。如果“对方”是您控制的内部 HTTP 客户端,请确保您可以为所欲为。
    【解决方案4】:

    您可以发送 401,然后在响应正文中您可以发送 window.location='domain.com'。但是,用户将在不知道发生 401 的情况下立即被重定向。

    【讨论】:

    • 用户不必知道发生了 401。用户不知道什么是 401。重定向耗时太长:下载响应正文、解析 HTML、解析 JS 等。
    【解决方案5】:

    这是一个干净的方法:

    在401页面,可以根据请求中的“accept”标头选择“view”发送。

    如果接受是application/json,那么你可以包含正文:

    {"status":401;"message":"Authentication required"}
    

    如果“接受”是text/html,那么你可以包含正文:

    <form action="/signin" method="post">
        <!-- bla bla -->
        <input type="hidden" name="redirect" value="[URL ENCODE REQUEST URI]">
    </form>
    

    然后您会遇到同样的问题...您是在成功登录时发出200 OK 还是302 Found? (看看我在那里做了什么?)

    如果您可以在任何页面上处理身份验证,则可以将表单操作设置为相同的页面 URL,但如果您将用户提供的 request_uri 放入表单操作属性中,请注意 XSS

    【讨论】:

      【解决方案6】:

      我来得很晚,但我想我会加两分钱。据我了解,希望表明用户没有正确的授权并提示他们登录。Rudie 可以理解地希望返回 401 Unauthorized (因为用户需要通过某种机制进行授权,例如登录in),并将它们转发到登录页面 - 但这不是很容易实现,并且大多数库不支持开箱即用。一种解决方案是在 401 响应的正文中显示登录页面,正如另一个答案中所建议的那样。但是,让我从既定/最佳实践的角度来看看这个。

      测试用例 1:Facebook

      在注销时导航到受保护的 Facebook 页面(我的用户个人资料)会导致 404 Not Found 响应。 Facebook 提供了一个通用的“此页面不可用”页面,其中还包括一个登录表单。有趣的。更有趣的是:当我导航到“事件”页面时,我收到一个 302 响应,该响应转发到登录页面(返回 200 响应)。所以我猜他们的想法是为我们知道存在的页面返回 302,但为可能存在或不存在的页面提供 404(例如,为了保护用户的隐私)。

      测试用例 2:Google 收件箱

      当我退出时导航到我的收件箱返回 302 并将我转发到一个登录页面,类似于 Facebook。我无法弄清楚如何将我的 Google+ 个人资料设为私有,因此那里没有测试数据...

      测试用例 3:Amazon.com

      当我退出时导航到我的订单历史会返回 302 并像以前一样将我转发到登录页面。亚马逊没有“个人资料”页面的概念,所以我也无法在这里进行测试。

      总结一下这里的测试用例,如果用户需要登录,最好返回 302 Found 并转发到登录页面(尽管我认为 303 See Other 实际上更合适)。这当然只是在真正的人类用户需要以 html 表单输入用户名和密码的情况下。对于其他类型的身份验证(例如基本、api 密钥等),401 Unauthorized 显然是适当的响应。在这种情况下,无需转发到登录页面。

      【讨论】:

      • 我喜欢这个答案。出于好奇,我尝试在未经身份验证的情况下请求我的一个私人亚马逊愿望清单的 URL,并收到 200 OK 响应!没有转发,但页面的正文确实显示了我的姓名和公开的愿望清单,以及一条消息说“我们很抱歉。您输入的网址不是我们网站上的正常页面。”可能是您确定的各种方法中最不可靠的!
      • 我认为大多数网站这样做的原因是为了计算登录页面。如果您的登录页面上有一个跟踪器,例如 Google Analytics,则最简单的计算方法是通过它的 URL。还有其他方法可以跟踪您可以添加到每个页面的特定标识符,但它们主要依赖于 Javascript。因此,如果 JS 未在 UA 上运行,则点击跟踪不会看到它。因此,对于像这样的大型网站,他们想要最简单、最简单的方法来计算登录等重要页面。所以这就是他们发送重定向而不是 401 的原因。
      • 我喜欢你的自然主义方法。 :-)
      【解决方案7】:

      Web 浏览器不是 REST 客户端。坚持发送带有 Location 标头且没有正文内容的状态 200。 30x 重定向适用于已移动的页面。不应期望其他状态代码/位置标头在 Web 浏览器中重定向。

      或者,您的网络服务器可能有可配置的错误页面。您可以将javascript添加到错误页面以进行重定向。

      【讨论】:

        猜你喜欢
        • 2017-09-17
        • 1970-01-01
        • 2021-06-17
        • 2014-12-02
        • 2014-01-05
        • 1970-01-01
        • 2016-07-30
        • 2015-12-29
        • 1970-01-01
        相关资源
        最近更新 更多