Skip to main content
 首页 » 编程设计

c#之来自 C# 客户端的 Apache NTLM Auth 不适用于自定义的 NetworkCredentials

2024年01月01日31exmyth

我有一个使用 HttpWebRequest 连接服务的办公插件。

在一个域中,我传递了 CredentialCache.DefaultNetworkCredentials,所以一切都很好。 在域外,用户需要提供用户名、域和密码。 这在 atm 上不起作用。

其中的部分代码:

CookieContainer cookies = new CookieContainer(); 
 
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
request.Method = WebRequestMethods.Http.Post; 
request.AllowAutoRedirect = true; 
request.CookieContainer = cookies; // provide session cookie to handle redirects of login controller of the webservice 
 
if (isWindowAuthentication) // isWindowAuthentication is set earlier by config 
{ 
  if (Common.UserName.Length > 0) 
  { 
    string[] domainuser; 
    string username; 
    string domain; 
 
    if (Common.UserName.Contains("@")) 
    { 
      domainuser = Common.UserName.Split('@'); 
      username = domainuser[0]; 
      domain = domainuser[1]; 
    } 
    else 
    { 
      domainuser = Common.UserName.Split('\\'); 
      username = domainuser[1]; 
      domain = domainuser[0]; 
    } 
    NetworkCredential nc = new NetworkCredential(username, Common.Password, domain); 
    CredentialCache cache = new CredentialCache(); 
    cache.Add(request.RequestUri, "NTLM", nc); 
    request.Credentials = cache; 
  } 
  else 
  { 
    request.Credentials = CredentialCache.DefaultNetworkCredentials; 
  } 
} 

稍后我执行请求 request.GetResponse();。 如果我使用 CredentialCache.DefaultNetworkCredentials 那么一切正常。 当我切换到我自己的 new NetworkCredential() 部分时,身份验证失败。

我检查了 Apache 的日志(它是使用 SSPI mod 的 Apache 2.2)。 当它成功时,第一个请求重定向到登录 Controller ,然后登录 Controller 请求凭据。通过并有效(重定向到目标站点)。

日志 1(有效):

192.168.14.9 - - [25/Oct/2012:11:35:35 +0200] "POST /ror/ioi/start?document%5Bguid%5D=%7Be3d8f1de-10f2-4493-a0c0-97c2acb034e6%7D HTTP/1.1" 302 202 
192.168.14.9 - - [25/Oct/2012:11:35:35 +0200] "GET /ror_auth/login?ror_referer=%2Fror%2Fioi%2Fstart%3Fdocument%255Bguid%255D%3D%257Be3d8f1de-10f2-4493-a0c0-97c2acb034e6%257D HTTP/1.1" 401 401 
192.168.14.9 - - [25/Oct/2012:11:35:35 +0200] "GET /ror_auth/login?ror_referer=%2Fror%2Fioi%2Fstart%3Fdocument%255Bguid%255D%3D%257Be3d8f1de-10f2-4493-a0c0-97c2acb034e6%257D HTTP/1.1" 401 401 
192.168.14.9 - rausch [25/Oct/2012:11:35:35 +0200] "GET /ror_auth/login?ror_referer=%2Fror%2Fioi%2Fstart%3Fdocument%255Bguid%255D%3D%257Be3d8f1de-10f2-4493-a0c0-97c2acb034e6%257D HTTP/1.1" 302 156 

这里自己的凭据结果Log 2(不工作):

192.168.14.9 - - [25/Oct/2012:12:05:23 +0200] "POST /ror/ioi/start?document%5Bguid%5D=%7B6ac54e8a-19f1-4ccd-9684-8d864dd9ccf7%7D HTTP/1.1" 302 202 
192.168.14.9 - - [25/Oct/2012:12:05:23 +0200] "GET /ror_auth/login?ror_referer=%2Fror%2Fioi%2Fstart%3Fdocument%255Bguid%255D%3D%257B6ac54e8a-19f1-4ccd-9684-8d864dd9ccf7%257D HTTP/1.1" 401 401 

我不明白的是当我检查例如CredentialCache.DefaultNetworkCredentials.UserName 然后是空的。

有人知道该怎么做以及我必须如何正确设置我自己的凭据才能使身份验证按预期工作吗?

请您参考如下方法:

经过大量测试和调查以及堆栈溢出的大量资源后,我终于发现了发生了什么。

问题似乎是 httpwebrequest 在部分网站请求凭据时不处理身份验证,而另一些则不。

背景:

我们的网站有自己的 session 管理,并在没有有效 session 可用时重定向到登录 Controller 。只有此登录 Controller 设置为 NTLM 身份验证。

我们这样做是因为我们有一个完全没有 NTLM 身份验证的网站(在 IE 中没有 401、302 请求循环!)并且只验证一次(我们在不同的 url 上处理身份验证以防止 IE 停止发布数据的问题未经身份验证的站点 => 请参阅 http://support.microsoft.com/?id=251404 )。

解决方案:

我通常在我的目标页面上发送请求,网络服务器重定向、验证并重定向回目标。由于 httpwebrequest 不会出于任何原因处理此问题,如果我有自己的凭据集(请参阅上面我的问题代码),我更改为代码以对我的登录 Controller 进行一次身份验证并将 session 存储在 cookie 容器中。

对于所有后续请求,我不再进行任何身份验证。我添加了 cookie 容器,我的服务器得到了一个有效的 session 。所以我不必再进行身份验证了。这种方式的副作用是性能更好。

另一个棘手的事情是我不仅使用了 httpwebrequest,我还使用了一个 webform 控件。 因此,我找到了在此处添加自己的 cookie session 的解决方案:Use cookies from CookieContainer in WebBrowser (感谢Aaron,他也为我省去了很多麻烦)。