奇怪的 HTTP 身份验证问题

Posted

技术标签:

【中文标题】奇怪的 HTTP 身份验证问题【英文标题】:Strange HTTP authentication issue 【发布时间】:2011-09-05 13:50:38 【问题描述】:

我在尝试使用 Digest 身份验证与 Web 服务器 (Apache 2.2.17) 通信并使用 POST 方法发送数据时遇到问题:它总是返回 401 错误。但是,当我们不发布数据或 Fiddler 正在运行时(即使在发布数据时),它也能正常工作...您知道什么会导致问题吗?

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();


【问题讨论】:

请展示一些源代码并比较一下通过网络传输的内容(有和没有 fiddler),例如使用 wireshark... 您需要显示源代码,我已经编写了许多 C# 代码,这些代码使用 HTTP 和摘要式身份验证发布数据,这些代码在生产中使用并且可以正常工作。所以要么你的代码有一些错误,要么存在服务器配置问题,没有示例代码/更多细节是不可能的! 我会尽快贴出源代码! 编辑:添加源代码。 感谢来源.. 你有没有比较过电线(用wireshark)什么时候工作和什么时候不工作? 【参考方案1】:

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

HTTP/401 表明服务器正在向客户端询问凭据。客户端应通过重新提交附加凭据的请求来响应。一个关键问题是,在失败的情况下是客户端尝试发送凭据但被拒绝,还是根本不尝试发送凭据?

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

【讨论】:

对不起,两次设置 Content-Type 标头是错误的。服务器 IP 是我们拥有的唯一信息...要回答您的关键问题,是的,客户端尝试发送凭据但被拒绝。 认为您是说服务器 IP 是您在 URL 中拥有的,而不是主机名?另外,您能否提供一个示例 URL(例如,是否有查询字符串参数)和服务器的摘要质询中的令牌(例如,它是否配置了完整性?)【参考方案2】:

HttpWebRequest.Create() 调用中的主机名(即 v_strUrl)是否与 credentialCache.Add() 调用中的主机名(即 ServerIP)相同?如果没有,那么这将永远失败。

不使用 CredentialCache,直接将凭据添加到 HttpWebRequest 对象

request.Credentials = new NetworkCredential("user", "password", "realm");

看看是否可行。

【讨论】:

【参考方案3】:

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

objHttpWebRequest.ServicePoint.Expect100Continue = false;

【讨论】:

以上是关于奇怪的 HTTP 身份验证问题的主要内容,如果未能解决你的问题,请参考以下文章

通过 Java 的 SFTP 连接要求奇怪的身份验证

使用 Twitch 进行身份验证时的 Spring-Boot OAuth2 奇怪行为

在 iOS 上通过 Spotify App Remote 的 SPTSession 进行身份验证时获取一个奇怪的刷新令牌

Laravel Passport 没有身份验证

在我的(java spring mvc + mysql application,thymeleaf)中实现spring security之后,身份验证发生了一些奇怪的事情

Laravel 未经身份验证无触发