这是HttpClient
和HttpWebRequest
类的默认行为,其暴露方式如下。
注意:下面的文字说明导致问题中描述的问题的次优行为。很可能你不应该这样写你的代码。相反,下面滚动到更正后的代码
在这两种情况下,实例化一个NetworkCredenatial
对象,并设置有
var credentials = new NetworkCredential(username, password);
如果使用HttpWebRequest
的用户名和密码 - 设置.Credentials
属性:
webRequest.Credentials = credentials;
如果您使用HttpClient
- 将凭证对象传递到HttpClientHandler
(从here更改的代码):
var client = new HttpClient(new HttpClientHandler() { Credentials = credentials })
然后运行Fiddler并开始请求。您将看到以下内容:
- 请求不授权头发送
- 服务回复与HTTP 401和WWW身份验证:基本境界=“UrRealmHere”
- 请求重新发送适当授权标题(和成功)
这种现象是说明here - 的CLIE nt事先并不知道该服务需要基本并试图协商认证协议(如果服务需要摘要发送基本打开头文件是无用的,可以危害客户端)。
注意:这里次优行为解释结束,并解释更好的方法。很可能你应该使用下面的代码而不是上面的代码。
的案件时,它知道该服务需要基本额外的要求可以消除通过以下方式:
不要设置.Credentials
,而不是使用代码手动添加here头。编码的用户名和密码:
var encoded = Convert.ToBase64String(Encoding.ASCII.GetBytes(
String.Format("{0}:{1}", username, password)));
当使用HttpWebRequest
将它添加到标题:
request.Headers.Add("Authorization", "Basic " + encoded);
,并使用HttpClient
时将其添加到默认的标题:
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", encoded);
当你这样做该请求每次都发送正确的授权标头。请注意,您不应设置.Credentials
,否则如果用户名或密码错误相同的请求将双方的时间与错误的凭据,当然产生HTTP的两次发送两次401
此解决方案以及它允许在第一个请求上设置授权标头,从而绕过401挑战/响应。但是,根据我对HttpClient和HttpClientHandler的经验,设置预认证的工作方式是,401挑战/响应完成后,每个请求都设置Authorize头。这篇文章解释得很好:http://weblog.west-wind.com/posts/2010/Feb/18/NET-WebRequestPreAuthenticate-not-quite-what-it-sounds-like – Philippe 2014-09-24 21:42:57
@Philippe:是的,太。谢谢。 – sharptooth 2014-09-26 12:31:40
提示:对于代理,您应该设置'client.DefaultRequestHeaders.ProxyAuthorization'标头。 – stil 2015-11-13 18:36:01