为什么我必须发送两个连续的HTTP Get请求进行身份验证?

时间:2013-12-16 10:05:21

标签: delphi http basic-authentication indy indy10

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

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

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

2 个答案:

答案 0 :(得分:6)

这是因为使用了 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(见图1)

如果您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块中,服务器告诉我可以使用哪些协议。

所以第二个请求不是,如果你认为认证失败,它就是设计的;因此,第一次请求不得发送用户名和密码。

答案 1 :(得分:1)

您需要确保:

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

  2. 有:

    一个。分配了OnAuthorization个事件处理程序,用于设置Authentication.UserNameAuthentication.Password参数,并将Handled参数设置为True。

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

  3. IdAuthentication...中指定的任何必要IdAuthenticationNTLM单位(例如IdAuthenticationSSPIIdAllAuthentications)或uses单位子句。

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