我的应用与需要身份验证的内部网络API进行通信。
当我发送请求时,我按预期获得401质询,发生握手,重新发送经过身份验证的请求,一切都继续正常。
但是,我知道需要使用身份验证。为什么我要等待挑战?我可以强制请求在第一个请求中发送凭据吗?
我的请求生成是这样的:
private static HttpWebRequest BuildRequest(string url, string methodType)
{
var request = HttpWebRequest.CreateHttp(url);
request.PreAuthenticate = true;
request.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
request.Credentials = CredentialCache.DefaultNetworkCredentials;
request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
request.ContentType = CONTENT_TYPE;
request.Method = methodType;
request.UserAgent = BuildUserAgent();
return request;
}
即使使用此代码,初始请求中也不包含auth标头。
我知道如何将auth信息包含在基本....我想要做的是使用执行应用程序的用户的Windows Auth(所以我不能将密码存储在配置文件中)。
更新我还尝试使用HttpClient
及其自己的.Credentials
属性,但结果相同:初始请求中没有添加auth标头。
我可以获取auth标头的唯一方式是使用基本身份验证手动破解它(在此用例中不会飞行)
答案 0 :(得分:8)
Ntlm是一种基于挑战/响应的身份验证协议。您需要发出第一个请求,以便服务器可以发出质询,然后在后续请求中客户端将响应发送给质询。然后,服务器通过向域控制器提供质询和客户端发送的响应来验证此响应。 在不知道挑战的情况下,您无法发送响应,这就是需要2个请求的原因。
基本身份验证是基于密码的,因此您可以通过发送带有第一个请求的凭据来使其短路,但根据我的经验,这可能是某些服务器需要处理的问题。
此处提供更多详细信息: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378749(v=vs.85).aspx
答案 1 :(得分:6)
我不是百分百肯定,但我怀疑没有办法解决这个问题;它只是HttpWebRequest
的工作方式。
在online .NET source,函数DoSubmitRequestProcessing
here中,您可以在函数开始后的第1731行看到此评论:
// We have a response of some sort, see if we need to resubmit
// it do to authentication, redirection or something
// else, then handle clearing out state and draining out old response.
向下一点(第1795行)(为简洁起见删除了一些行)
if (resubmit)
{
if (CacheProtocol != null && _HttpResponse != null) CacheProtocol.Reset();
ClearRequestForResubmit(ntlmFollowupRequest);
...
}
在ClearRequestForResubmit
第5891行:
// We're uploading and need to resubmit for Authentication or Redirect.
然后(第5923行):
// The second NTLM request is required to use the same connection, don't close it
if (ntlmFollowupRequest) {....}
对于我(公认的n00bish )的眼睛,这些评论似乎表明开发人员决定遵循"标准"针对NTML / Kerberos的质询 - 响应协议,不包括任何预先发送身份验证标头的方法。
答案 2 :(得分:2)
设置PreAuthenticate就是您想要的,您正在做的事情。第一个请求仍将执行握手,但对于后续请求,它将自动发送凭据(基于所使用的URL)。您可以在此处阅读:http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.preauthenticate(v=vs.110).aspx。