2011-09-05 113 views
0

尝试使用摘要式身份验证与Web服务器(Apache 2.2.17)通信并使用POST方法发送数据时遇到问题:它始终返回401错误。但是,如果我们不发布数据,或者当Fiddler正在运行(即使发布数据时),它也会运行良好......您是否了解可能导致问题的原因?奇怪的HTTP身份验证问题

public void DoRequest(string v_strURL, XmlDocument v_objXMLDoc) 
{ 

var credentialCache = new CredentialCache(); 

credentialCache.Add(new Uri("http://" + ServerIP + "/"), "Digest", new NetworkCredential("admin", "test", "realm")); 

String RequestContent = "request=" + v_objXMLDoc.InnerXml.Replace(' ', '+'); 
Uri Url = new Uri(v_strURL); 

HttpWebRequest objHttpWebRequest; 
HttpWebResponse objHttpWebResponse = null; 

Stream objRequestStream = null; 

byte[] bytes = new byte[0]; 
bytes = System.Text.Encoding.UTF8.GetBytes(RequestContent); 

objHttpWebRequest = (HttpWebRequest)WebRequest.Create(v_strURL); 
objHttpWebRequest.UserAgent = "MySampleCode"; 
objHttpWebRequest.Credentials = credentialCache; 
objHttpWebRequest.Method = "POST"; 
objHttpWebRequest.ContentLength = bytes.Length; 
objHttpWebRequest.ContentType = "text/xml; encoding='utf-8'"; 
objHttpWebRequest.ContentType = "application/x-www-form-urlencoded"; 

objRequestStream = objHttpWebRequest.GetRequestStream(); 
objRequestStream.Write(bytes, 0, bytes.Length); 
objRequestStream.Close(); 

objHttpWebResponse = (HttpWebResponse)objHttpWebRequest.GetResponse(); 

} 
+1

请出示一些源代码和 – Yahia

+0

你需要显示源代码比较有什么越过线(有和没有小提琴手),例如使用Wireshark ...我写了大量的C#代码,它们使用HTTP发布数据并摘要身份验证,这些身份验证在生产环境中使用并且没有问题。因此,无论您的代码是否存在一些错误,或者存在服务器配置问题,没有示例代码/更多细节,都无法分辨! – RobV

+0

我会尽快发布源代码! – JoRoy

回答

0

我们终于解决了这个问题:

objHttpWebRequest.ServicePoint.Expect100Continue = false; 
2

是否有某些原因需要设置Content-Type标头两次?这不太可能做你想做的事情。另外,为什么你把信誉放在服务器IP而不是主机名的缓存中?

HTTP/401表明服务器正在挑战客户端的凭证。预计客户端将通过重新提交带有凭证的请求进行响应。一个关键问题是,在失败的情况下,客户端是否尝试发送凭证,并且他们被拒绝,或者根本没有尝试发送凭证?

如果Fiddler“神奇地”为您解决问题,您可能应该使用Netmon或Wireshark进行低级外观。

+0

对不起,设置Content-Type头两次是一个错误。服务器IP是我们唯一的信息......要回答您的关键问题,是的,客户端尝试发送凭据,他们被拒绝。 –

+0

我*认为*你是说服务器IP是你在URL中而不是主机名?另外,您能否提供示例URL(例如,是否存在查询字符串参数)以及服务器摘要挑战中的令牌(例如,它是否配置为完整性?) – EricLaw

1

您的HttpWebRequest.Create()调用(即v_strUrl)中的主机名是否与调用credentialCache.Add()(即ServerIP)时的主机名相同?如果不是,那么这总是会失败。

代替使用CredentialCache的,只是直接添加凭据HttpWebRequest对象

request.Credentials =新的NetworkCredential( “用户”, “密码”, “域”);

看看是否有效。