使用基于表单的身份验证时,http 服务器应在 401 响应中返回啥 WWW-Authenticate 标头?

Posted

技术标签:

【中文标题】使用基于表单的身份验证时,http 服务器应在 401 响应中返回啥 WWW-Authenticate 标头?【英文标题】:What WWW-Authenticate header should a http server return in a 401 response when using form-based authentication?使用基于表单的身份验证时,http 服务器应在 401 响应中返回什么 WWW-Authenticate 标头? 【发布时间】:2018-07-02 16:11:51 【问题描述】:

我有一个在浏览器上运行的带有 javascript 部分的 Web 应用程序。该前端使用多个 HTTP 端点(或多或少 REST)。前端必须能够区分401403 响应,并且不得接收通常用于人类用户的3xx 重定向。

通过纯表单登录完成授权(其中不涉及 Javascript),然后使用会话 cookie(用于“REST”和普通请求)。

WWW-Authenticate 标头值的正确值是多少?

来自RFC 7235:“生成 401(未经授权)响应的服务器必须发送包含至少一个质询的 WWW-Authenticate 标头字段。”

Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry 没有列出任何基于表单的身份验证方案。

另见:

HTTP 401 Unauthorized when not using HTTP basic auth? Authorization in RESTful HTTP API, 401 WWW-Authenticate

【问题讨论】:

刚刚发明了“基于表单”的方案。只有 IANA 注册待处理;-)。 【参考方案1】:

WWW-Authenticate 标头值的正确值是多少?

当您不使用RFC 7235 中所述的 HTTP 身份验证时,返回 401WWW-Authenticate 是没有意义的。在 HTTP 身份验证中,客户端应使用 authentication scheme 令牌在请求的 Authorization 标头中发送凭据。

如果您想使用POST 在请求负载中发送凭据,则403 状态码更适合表明服务器已拒绝该请求。

【讨论】:

【参考方案2】:

由于这种类型的身份验证没有标准挑战,因此您(正如您自己预测的那样)发明了自己的。

我认为这里没有指定供应商令牌的标准机制,所以我认为您能做的最好的事情是使用不太可能与其他任何东西发生冲突的令牌。

亚马逊已经通过AWS 做到了这一点,还有很多其他的。我的建议是使用productname-schemename 之类的东西,例如acme-webauth

【讨论】:

【参考方案3】:

没有用于基于表单的身份验证的 HTTP 身份验证方案。 浏览器通过显示一个可以输入凭据的弹出窗口来实现基本、摘要等。

【讨论】:

这基本上就是我所说的“超文本传输​​协议 (HTTP) 身份验证方案注册表没有列出任何基于表单的身份验证方案。”,不是吗?现在,我应该发明一个方案吗?我想我不是第一个遇到这个问题的人。浏览器托管 Javascript 应用程序,这些应用程序可能比浏览器本身理解更多的东西。那么,如果没有正式规范,也许是最佳实践? WWW-Authenticate 不与基于表单的身份验证一起使用 - 周期。您将不得不使用 403 而不是 401 如果你“发明”你的“基于表单”的方案,你仍然有你发送的问题,例如带有一些应用程序/x-www-form-urlencoded 凭据的 POST 请求,这是错误的并且不是预期的。您必须使用 WWW-Authenticate 请求标头来提供凭据,并且您必须将它们与每个后续请求一起发送,因为在 HTTP 中,通信必须是无状态的。 @spaceone 我不认为 RFC7235 声明 WWW-Authenticate 标头需要使用 Authorization 标头进行身份验证。我找不到任何支持这一点的语言。 从我的角度来看,WWW-Autentication 标头只是表示需要身份验证,并且有一个令牌指示应该使用什么协议。身份验证语义取决于令牌。【参考方案4】:

理论上你应该回应

HTTP/1.x 401 Unauthorized
WWW-Authenticate: cookie; cookie-name=my-session-cookie-name

但是,现实世界的互联网浏览器(用户代理)并不真正支持这一点,根据我的经验,最不坏的选择是对所有“拒绝访问”使用 HTTP 状态 403,“未经授权”和“不允许”。如果您有一个通过非浏览器用户代理访问的 REST 服务,您可以按照规范并返回上述标头。

如 RFC 7231 第 6.5.4 节 (https://www.rfc-editor.org/rfc/rfc7231#section-6.5.4) 中所述,服务器可以用 404 响应“拒绝访问”和“未找到”,因此对于所有用户代理(浏览器)来说,以下应该是可以的:

403: "Unauthorized" or "Not allowed"
404: "Access Denied" or "Not Found"

或者您可以在任何情况下使用400,因为这会导致浏览器回退到通用错误处理情况。状态码 401 尤其成问题,因为它在历史上意味着(至少在实践中)使用了基本领域身份验证并且不接受提交的 HTTP 标头 Authorization。由于您无法通过该标头在常用浏览器中提交会话 cookie,因此当您使用 cookie 进行身份验证时,这些浏览器无法正确处理 401。

【讨论】:

更多详情请见tools.ietf.org/id/draft-broyer-http-cookie-auth-00.html

以上是关于使用基于表单的身份验证时,http 服务器应在 401 响应中返回啥 WWW-Authenticate 标头?的主要内容,如果未能解决你的问题,请参考以下文章

用于 HTTPS 应用程序的基于表单的身份验证 OWASP ZAP

ASP.NET MVC 4 (十三) 基于表单的身份验证

使用 Spring security Javaconfig 进行基本和基于表单的身份验证

使用 oAuth 和基于表单的身份验证配置 Spring Security

Spring Cloud OAuth2:身份验证后再次重定向到登录页面,就像使用表单登录时未经身份验证一样

SOAPUI中文教程---基于表单的身份验证