【问题标题】:Why do I have to send two consecutive HTTP Get requests to be authenticated?为什么我必须发送两个连续的 HTTP Get 请求才能进行身份验证?
【发布时间】:2013-12-16 10:05:20
【问题描述】:

这是a prior question of mine 的后续问题。我了解到,在请求中使用 HTTP 用户名/密码参数时,有 2 个不同的 Get 请求将发送到服务器。第一次尝试不包括用户名/密码凭据,但如果身份验证失败,它会发送另一个包含这些凭据的相同请求。

然而,在使用 Indy 的 TIdHTTP 时,它只发送一个请求,并以 Unauthorized 失败。实际上需要第二个相同的连续请求才能真正获得所需的响应。

我想知道,这是设计使然,还是 Indy 的缺陷?

【问题讨论】:

  • 你不需要处理OnAuthorization事件吗?
  • 查看 IdHttpInstance.Request.UserName & Password 属性
  • @ComputerSaysNo 遥遥领先 :-)

标签: delphi http basic-authentication indy indy10


【解决方案1】:

这是因为使用了HTTP Negotiate认证方式:

"NTLM and Negotiate (RFC-4559) is most commonly used on Microsoft IIS web servers. NTLM can be used exclusively, but modern servers typically use Negotiate to select which scheme will be used. The result is usually NTLM'

Microsoft explains it e.g. here(见图一)

如果您Google for http request negotiation www-authenticate,您会找到更多信息。

作为说明,如果 SOAPUI 与 Exchange Web 服务建立经过身份验证的连接,这是我看到的 HTTP:

1>  >> "POST /ews/exchange.asmx HTTP/1.1[\r][\n]"
    >> "Accept-Encoding: gzip,deflate[\r][\n]"
    >> "SOAPAction: "http://schemas.microsoft.com/exchange/services/2006/messages/ResolveNames"[\r][\n]"
    >> "Content-Type: text/xml; charset=utf-8[\r][\n]"
    >> "Content-Length: 548[\r][\n]"
    >> "Host: webmail.ttbv.nl[\r][\n]"
    >> "Connection: Keep-Alive[\r][\n]"
    >> "User-Agent: Apache-HttpClient/4.1.1 (java 1.5)[\r][\n]"
    >> "[\r][\n]"
    >> "<soapenv:Envelope [\n]"
    [snip]
    >> "</soapenv:Envelope>[\n]"
    >> "[\n]"

1<  << "HTTP/1.1 401 Unauthorized[\r][\n]"
    << "Cache-Control: private[\r][\n]"
    << "Server: Microsoft-IIS/7.5[\r][\n]"
    << "X-AspNet-Version: 2.0.50727[\r][\n]"
    << "Set-Cookie: exchangecookie=a29f10ca2a6d484ea276737e87d8e733; expires=Wed, 13-Nov-2013 10:47:33 GMT; path=/; HttpOnly[\r][\n]"
    << "WWW-Authenticate: Negotiate[\r][\n]"
    << "WWW-Authenticate: NTLM[\r][\n]"
    << "X-Powered-By: ASP.NET[\r][\n]"
    << "Date: Tue, 13 Nov 2012 10:47:33 GMT[\r][\n]"
    << "Content-Length: 0[\r][\n]"
    << "[\r][\n]"

2>  >> "POST /ews/exchange.asmx HTTP/1.1[\r][\n]"
    >> "Accept-Encoding: gzip,deflate[\r][\n]"
    >> "SOAPAction: "http://schemas.microsoft.com/exchange/services/2006/messages/ResolveNames"[\r][\n]"
    >> "Content-Type: text/xml; charset=utf-8[\r][\n]"
    >> "Content-Length: 548[\r][\n]"
    >> "Host: webmail.ttbv.nl[\r][\n]"
    >> "Connection: Keep-Alive[\r][\n]"
    >> "User-Agent: Apache-HttpClient/4.1.1 (java 1.5)[\r][\n]"
    >> "Cookie: exchangecookie=a29f10ca2a6d484ea276737e87d8e733[\r][\n]"
    >> "Cookie2: $Version=1[\r][\n]"
    >> "Authorization: NTLM TlRMTVNTUAAB[snip]QgBWAA==[\r][\n]"
    >> "[\r][\n]"
    >> "<soapenv:Envelope [\n]"
    [snip]
    >> "</soapenv:Envelope>[\n]"
    >> "[\n]"

2<  << "HTTP/1.1 401 Unauthorized[\r][\n]"
    << "Server: Microsoft-IIS/7.5[\r][\n]"
    << "WWW-Authenticate: NTLM TlRMTVNTU[snip]AACAAAAFAAAAA==[\r][\n]"
    << "WWW-Authenticate: Negotiate[\r][\n]"
    << "X-Powered-By: ASP.NET[\r][\n]"
    << "Date: Tue, 13 Nov 2012 10:47:33 GMT[\r][\n]"
    << "Content-Length: 0[\r][\n]"
    << "[\r][\n]"

3>  >> "POST /ews/exchange.asmx HTTP/1.1[\r][\n]"
    >> "Accept-Encoding: gzip,deflate[\r][\n]"
    >> "SOAPAction: "http://schemas.microsoft.com/exchange/services/2006/messages/ResolveNames"[\r][\n]"
    >> "Content-Type: text/xml; charset=utf-8[\r][\n]"
    >> "Content-Length: 548[\r][\n]"
    >> "Host: webmail.ttbv.nl[\r][\n]"
    >> "Connection: Keep-Alive[\r][\n]"
    >> "User-Agent: Apache-HttpClient/4.1.1 (java 1.5)[\r][\n]"
    >> "Cookie: exchangecookie=a29f10ca2a6d484ea276737e87d8e733[\r][\n]"
    >> "Cookie2: $Version=1[\r][\n]"
    >> "Authorization: NTLM TlRMTVNT[snip]AVABUADcANAA=[\r][\n]"
    >> "[\r][\n]"
    >> "<soapenv:Envelope [\n]"
    [snip]
    >> "</soapenv:Envelope>[\n]"
    >> "[\n]"

3<  << "HTTP/1.1 200 OK[\r][\n]"
    << "Cache-Control: private[\r][\n]"
    << "Transfer-Encoding: chunked[\r][\n]"
    << "Content-Type: text/xml; charset=utf-8[\r][\n]"
    << "Server: Microsoft-IIS/7.5[\r][\n]"
    << "X-EwsPerformanceData: RpcC=2;RpcL=0;LdapC=1;LdapL=0;[\r][\n]"
    << "X-AspNet-Version: 2.0.50727[\r][\n]"
    << "Persistent-Auth: true[\r][\n]"
    << "X-Powered-By: ASP.NET[\r][\n]"
    << "Date: Tue, 13 Nov 2012 10:47:33 GMT[\r][\n]"
    << "[\r][\n]"
    << "877[\r][\n]"
    << "<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    [snip]
    << "</s:Envelope>"
    << "[\r][\n]"
    << "0[\r][\n]"
    << "[\r][\n]"

在收到的第一个 HTTP 块中,服务器告诉我可以使用哪些协议。

所以第二个请求不是,就像你写的那样如果身份验证失败,这是设计使然;因此第一个请求不需要发送用户名和密码。

【讨论】:

  • 是的,但是,TIdHTTP 旨在处理此类情况并自动发送后续身份验证要求,而无需用户手动执行。
【解决方案2】:

您需要确保:

  1. TIdHTTP.HTTPOptions 属性中启用hoInProcessAuth 标志。

  2. 有一个:

    一个。分配的 OnAuthorization 事件处理程序将 Authentication.UserNameAuthentication.Password 参数以及 Handled 参数设置为 True。

    b.分配给 TIdHTTP.Request.Password 属性的非空白字符串。

  3. 任何必要的IdAuthentication... 单位(例如IdAuthenticationNTLMIdAuthenticationSSPI),或IdAllAuthentications 单位,在uses 子句中指定。

如果不满足这些条件,TIdHTTP 将不会尝试处理基于 HTTP 的身份验证。

【讨论】:

  • [向 Remy 发送虚拟啤酒] 这解决了所有问题,也回答了我之前的问题 :-)
  • 特别是 hoInProcessAuth 部分修复了这一切
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-05
  • 2010-12-03
  • 1970-01-01
  • 2017-07-23
  • 2016-09-29
  • 2023-03-31
相关资源
最近更新 更多