如何使用HttpWebRequest.Credentials属性进行基本身份验证?

4

如何使用Webrequest的Credentials属性发送基本认证头?即使设置了PreAuthenticate为true,为什么请求中没有发送Authorization头?

WebRequest request = (HttpWebRequest)WebRequest.Create("https://api.github.com/user");
request.Credentials = new NetworkCredential("githubUsername", "githubPassword");
request.PreAuthenticate = true;
var response = request.GetResponse();
3个回答

5
服务器应该发送一个HTTP 401未授权的响应代码,其中包含一个WWW-Authenticate HTTP头。
WWW-Authenticate: Basic realm="example"

PreAuthenticate属性仅在身份验证完成后起作用。来自MSDN的解释:

如果需要在身份验证完成后发送带有HTTP Authorization头的请求,则为true;否则为false。默认值为false。

更深入的解释请参见其他答案。

谢谢Jos。现在我更加了解了。 - user628985

4
我根据Måns Tånneryd的回答进行了一些额外的研究。他在评论中发布的链接是:WebRequest的PreAuthenticate属性-问题
首先,如他的链接所述,HttpWebRequest.PreAuthenticate Property不会在预身份验证时发送身份验证标头,而是在身份验证后的后续请求中发送它们。来自MSDN的描述如下:
“如果要在身份验证之后的请求中发送HTTP授权标头,则为true;否则为false。默认值为false。”
因此,即使将 PreAuthenticate 属性设置为true,我们仍然需要401未经授权的WWW-Authenticate挑战才能发生任何事情。现在,如果我们尝试使用以下代码对github进行身份验证:
WebRequest request = (HttpWebRequest)WebRequest.Create("https://api.github.com/user");
request.Credentials = new NetworkCredential("githubUsername", "githubPassword");

var response = request.GetResponse();

由于我们没有收到WWW-Authenticate挑战,将会抛出WebException异常。如果我们在Fiddler中捕获到这个异常,我们将得到以下内容:

enter image description here

然而,如果我们使用完全相同的代码对返回WWW-Authenticate挑战的网站进行尝试,我们将在Fiddler中看到以下内容:

enter image description here enter image description here

响应将会如预期一样返回结果。


3
我可以成功运行此代码,访问另一个需要SSL和身份验证的服务器。这个服务器与github不同,因为github返回一个JSON结果,指出需要身份验证,而另一个服务器返回一个“经典”的401 HTML页面。通过嗅探网络,您可以看到.NET代码尝试进行匿名身份验证,即使您将preauth设置为true,我认为这是相当令人困惑的。然而,在收到常规的401页面后,它会再次尝试,这次包含身份验证信息,一切正常。不过,对于.NET来说,似乎在收到401的json版本时会有不同的反应,不会再次尝试。
我想这可能不是您要寻找的答案,但希望它能更深入地解释情况。

1
我在Charles Cook的博客上找到了解释和解决方案。解释在http://www.cookcomputing.com/blog/archives/000580.html,解决方案可以在http://www.cookcomputing.com/blog/archives/000581.html找到。 - Måns Tånneryd
谢谢你的回答,它为这种情况提供了很好的解释。你提供的链接也很有帮助。今晚我会花更多时间尝试在另一台服务器上进行身份验证,看看是否能够成功。你尝试的服务器是公共服务器吗?我也可以尝试进行身份验证吗?我仍然想知道是否有一种方法可以使用凭据属性/通过它来验证Github中的JSON 401。所以我现在将问题保持开放状态。 - Jos Vinke
我使用的服务器很不幸,不是公共的。 - Måns Tånneryd
谢谢Måns!我已经解决了,并在另一个答案中分享了一些发现,我已将您的答案标记为已接受。 - Jos Vinke
很高兴能够提供帮助。我之前遇到过这种情况,但从未花时间弄清楚为什么预授权属性没有产生我期望的行为,只是接受了请求往返两次而不是一次的事实。 - Måns Tånneryd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接