虽然401 Unauthorized
可能看起来很漂亮(" Access令牌丢失或无效")但它可以抛出许多客户端HTTP堆栈来提示用户输入凭据,这是赢得了#39 ;无论如何都要成功,因为普通的HTTP身份验证机制还没有发挥作用。
虽然我可以绕道使用另一个我可以指示不尝试自动身份验证或用户提示的客户端库(并且已经这样做了),但据我所知,这似乎违反了RFC 7235。
我怀疑403 Forbidden
在这里会更加合规,而且API用户也不会感到悲伤。他们中的大多数可能只是看到任何非2XX状态并立即运行以寻找JSON"错误"反应的身体。
我绕道而行,所以我不抱怨,但这里似乎有点可疑。我当然错过了什么?现在通常的做法是以这种方式将401
用于类似REST的HTTP API吗?
更多细节
只要使用了正确的身份验证令牌,它就会起作用,但如果使用了坏令牌,则会导致用户/ pw的GUI提示:
Set JsonBag = PBConfig.CloneItem("CreatePushJson") 'Make a deep copy of template JSON.
With JsonBag
.Item("title") = txtTitle.Text
.Item("body") = txtBody.Text
End With
With XMLHTTP
.abort 'Clean up previously failed request if any.
.open "POST", PBConfig.Item("CreatePushUrl"), True
.setRequestHeader "Access-Token", PBConfig.Item("AccessToken")
.setRequestHeader "Content-Type", "application/json"
.onreadystatechange = SinkRSChange
.send JsonBag.JSON
End With
如果用户取消了提示,则会向代码报告401
。
根据以下信息,我尝试将身份验证令牌作为用户ID值发送。但是,即使身份验证令牌正确,这也会引发提示:
Set JsonBag = PBConfig.CloneItem("CreatePushJson") 'Make a deep copy of template JSON.
With JsonBag
.Item("title") = txtTitle.Text
.Item("body") = txtBody.Text
End With
With XMLHTTP
.abort 'Clean up previously failed request if any.
.open "POST", PBConfig.Item("CreatePushUrl"), True, PBConfig.Item("AccessToken")
.setRequestHeader "Content-Type", "application/json"
.onreadystatechange = SinkRSChange
.send JsonBag.JSON
End With
如果用户手动将有效的身份验证令牌作为用户ID输入到提示中,则请求会成功。
根据以下新信息
这可以通过明确地发送"."
作为密码来实现:
Set JsonBag = PBConfig.CloneItem("CreatePushJson") 'Make a deep copy of template JSON.
With JsonBag
.Item("title") = txtTitle.Text
.Item("body") = txtBody.Text
End With
With XMLHTTP
.abort 'Clean up previously failed request if any.
.open "POST", PBConfig.Item("CreatePushUrl"), True, PBConfig.Item("AccessToken"), "."
.setRequestHeader "Content-Type", "application/json"
.onreadystatechange = SinkRSChange
.send JsonBag.JSON
End With
正确的令牌值有效,错误的令牌值会返回可以处理它的401
。现在没有凭据提示对话框。
答案 0 :(得分:0)
正常的HTTP身份验证机制在技术上正在发挥作用。 api甚至会要求您的浏览器提供凭据,以便您可以在浏览器中执行请求(有人实际请求了这些请求)。
对401s有特殊行为的HTTP库似乎确实存在问题,但有一次它发生了我能够禁用魔法401处理。我不知道谁在这里违反了RFC 7235。 RFC 2616 10.4.2似乎表明当前的行为是正确的"。您是否有提示用户提供凭据的HTTP客户端列表?
也许403在这里更有意义,但Stripe至少似乎使用401:https://stripe.com/docs/api#errors而且它们都是关于REST的。切换到403也会破坏所有现有客户端。大多数客户实际上并不奇怪地看待JSON主体,他们只是查看状态代码。
我认为如果我创建另一个HTTP API,它将只有200/400/500状态代码,其中包含JSON编码主体的POST和JSON响应。
答案 1 :(得分:0)
替代:
如果不需要支持Windows的下层版本,则可以使用WinHttp.WinHttpRequest对象替代上述问题示例中使用的MSXML2.XMLHTTP对象。
Set JsonBag = PBConfig.CloneItem("CreatePushJson") 'Make a copy.
JsonBag("title") = txtTitle.Text
JsonBag("body") = txtBody.Text
With WinHttp
.Abort 'Clean up previously failed request if any.
.Open "POST", PBConfig("CreatePushUrl"), True
.SetAutoLogonPolicy AutoLogonPolicy_Never
.SetRequestHeader "Access-Token", PBConfig("AccessToken")
.SetRequestHeader "Content-Type", "application/json"
.Send JsonBag.JSON
End With
这个问题的关键是.SetAutoLogonPolicy AutoLogonPolicy_Never
我们没有老班级可以使用。
请注意,此示例使用了一个事实,即JsonBag具有.Item()
作为其默认属性...以防万一您想知道此代码段与之前的代码片段之间的差异。它与WinHttp的使用无关,也可以在早期的片段中以这种方式编写。