如何使用基于 HttpClient 和 .net4 的 Rest-client 进行身份验证

Posted

技术标签:

【中文标题】如何使用基于 HttpClient 和 .net4 的 Rest-client 进行身份验证【英文标题】:How to authenticate with Rest-client based on HttpClient and .net4 【发布时间】:2011-11-15 06:39:13 【问题描述】:

已经详细说明了使用 HttpClient 构建一个 REST 客户端。但我无法弄清楚,也找不到任何关于如何向服务器进行身份验证的示例。我很可能会使用基本的 aut,但实际上任何示例都会受到赞赏。

在早期版本(网上有示例)中,您这样做了:

HttpClient client = new HttpClient("http://localhost:8080/ProductService/");
client.TransportSettings.Credentials =
    new System.Net.NetworkCredential("admin", "admin");

但是,TransportSettings 属性在 0.3.0 版中不再存在。

【问题讨论】:

【参考方案1】:

所有这些都过时了。最后的方法如下:

var credentials = new NetworkCredential(userName, password);
var handler = new HttpClientHandler  Credentials = credentials ;

using (var http = new HttpClient(handler))

    // ...

【讨论】:

我正在使用 VS2013 和 .NET 4.5 未设置授权标头。我只能通过属性直接设置标题。我还能错过什么? @Alex 尝试设置 HttpClientHandler.PreAuthenticate = true msdn.microsoft.com/en-us/library/… 太棒了。 @DuncanSmart 值得再多一个 +1【参考方案2】:

HttpClient 库没有进入 .Net 4。但是它可以在此处http://nuget.org/List/Packages/HttpClient 获得。但是,在这个版本的 HttpClient 中,身份验证的方式有所不同。

var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization 
                   = new AuthenticationHeaderValue("basic","...");

var webRequestHandler = new WebRequestHandler();
CredentialCache creds = new CredentialCache();
creds.Add(new Uri(serverAddress), "basic",
                        new NetworkCredential("user", "password"));
webRequestHandler.Credentials = creds;
var httpClient = new HttpClient(webRequestHandler);

请注意,此库将在下周更新,并且会有一些小的重大更改!

【讨论】:

是的,很抱歉让您感到困惑。那是我得到的版本,来自 nuget 的版本。 我玩过这个,但我似乎无法让它发挥作用。但据我了解,“...”应该是 uname:pwd base64 编码的? 嗯...以为我可以正常工作,但无法使用基本身份验证和抢先身份验证...感谢您的指导。 谢谢,这对我也很有用。我唯一要补充的是,某些服务器的标头区分大小写,并且更喜欢“基本”而不是“基本”。 (我自己发现了这个)【参考方案3】:

我尝试了 Duncan 的建议,但在我的情况下不起作用。我怀疑这是因为我正在与之集成的服务器没有发送质询或要求身份验证。它只是拒绝了我的请求,因为我没有提供 Authorization 标头。

所以我改为执行以下操作:

using (var client = new HttpClient())

    var encoding = new ASCIIEncoding();
    var authHeader = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(encoding.GetBytes(string.Format("0:1", "username", "password"))));
    client.DefaultRequestHeaders.Authorization = authHeader;
    // Now, the Authorization header will be sent along with every request, containing the username and password.

请注意,此处的示例仅适用于 Basic authentication。

【讨论】:

【参考方案4】:

从 .NET 4.8、.NET core 3.1 和 .NET Standard 2.0 开始,他们建议同时使用 HttpClientCredentialCache。像这样的:

const string basicAuthUser = @"myUser";
const string basicAuthPass = @"myPass";
const string host = @"https://my.host.com";
const string path = @"/api";

using (var httpClientHandler = new HttpClientHandler()) 
    httpClientHandler.PreAuthenticate = true;
    httpClientHandler.UseDefaultCredentials = true;

    var basicCredCache = new CredentialCache();
    var basicCredentials = new NetworkCredential(basicAuthUser, basicAuthPass);
    basicCredCache.Add(new Uri(new Uri(host), path), "Basic", basicCredentials);
    httpClientHandler.Credentials = basicCredCache;

    using (var client = new HttpClient(httpClientHandler)) 
        client.BaseAddress = new Uri(host);
        using (var request = new HttpRequestMessage(HttpMethod.Get /*HttpMethod.Post*/, path)) 
            //
            // Send request here
            //
        
    

编辑:请注意,将 HttpClient 包装到 using 可能会导致高负载下的 Socket 耗尽。然而,将HttpClient 保持为单例可能会导致其他问题,例如过时的 DNS 问题。从here开始阅读这篇长篇故事。

【讨论】:

【参考方案5】:

对于它的价值,使用 HttpClientHandler 没有任何效果,至少不能尝试对需要服务器管理员凭据的 CouchDB API 进行经过身份验证的调用。

这对我有用:

using( var client = new HttpClient() )

    var byteArray = Encoding.ASCII.GetBytes("MyUSER:MyPASS");
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
    ....

正如这里的答案所述:

How to use credentials in HttpClient in c#?

【讨论】:

这和@Renè answer here above一样吗?【参考方案6】:

我相信这有点老了,但对于任何寻找更新答案的人来说,我在构建测试服务器时使用了这段代码:

        using (var client = new HttpClient())
        
            client.BaseAddress = new Uri("http://myServer/api/Person");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var byteArray = Encoding.ASCII.GetBytes($"UserName:ApiPassword");
            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

或者这也可以:

            using (var http = new HttpClient())
            
                // byteArray is username:password for the server
                var byteArray = Encoding.ASCII.GetBytes("myUserName:myPassword");
                http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
                string uri = "http://myServer/api/people" ;
                var response = await http.GetStringAsync(uri);
                List<Person> agencies = JsonConvert.DeserializeObject<List<Person>>(response);
                foreach (Person person in people)
                
                    listBox1.Items.Add(person.Name);
                
            

【讨论】:

【参考方案7】:

我刚刚下载了 0.3.0,它确实被删除了。现在在HttpClientChannel

HttpClient client = new HttpClient(...);
var channel = new HttpClientChannel();
channel.Credentials = new NetworkCredential(...);
client.Channel = channel;

如果没有明确指定,它将使用HttpClientChannel 的默认实例。

更新:现在对 .Net 4.5 无效;请看下面的正确答案:https://***.com/a/15034995/58391

【讨论】:

那是旧版本?我正在使用 nuget 的 0.3.0。 @Thomas RSK 中的那个是原型。另一个团队根据他们从原型中学到的知识重新编写了 nuget 版本。 @codekaizen 这个问题是指 .Net 4,在 .NET 4.5 发布之前被问到/回答过。 当然,明白,但现在它出现在同一问题的搜索结果中,为当前的事态提供指导很重要。【参考方案8】:

仅在指定DefaultRequestHeaders 时有效。其他方式都行不通。

【讨论】:

以上是关于如何使用基于 HttpClient 和 .net4 的 Rest-client 进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 HttpClient 类时如何对代理进行身份验证?

如何在 C# (.NET 4.5) 中为 HttpClient.GetAsync(URI) 创建回调?

.NET 4.5 和 C# 中带有 HttpClient 的 HTTP HEAD 请求

如何使用 .Net 4.0 中包含的 HttpClient 类将文件上传到在 IIS Express 中运行的 Asp.Net MVC 4.0 操作

使用 HttpClient.GetAsync() 时如何确定 404 响应状态

如何正确设置 HttpClient 的延续?