2012-04-09 30 views
18

Tôi đang cố gắng sử dụng một HttpClient cho dịch vụ của bên thứ ba yêu cầu xác thực HTTP cơ bản. Tôi đang sử dụng AuthenticationHeaderValue. Đây là những gì tôi đã đưa ra cho đến nay:HttpClient tiêu đề xác thực không nhận được gửi

HttpRequestMessage<RequestType> request = 
    new HttpRequestMessage<RequestType>(
     new RequestType("third-party-vendor-action"), 
     MediaTypeHeaderValue.Parse("application/xml")); 
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
     string.Format("{0}:{1}", "username", "password")))); 

var task = client.PostAsync(Uri, request.Content); 
ResponseType response = task.ContinueWith(
    t => 
    { 
     return t.Result.Content.ReadAsAsync<ResponseType>(); 
    }).Unwrap().Result; 

Dường như hành động POST hoạt động tốt, nhưng tôi không lấy lại dữ liệu tôi mong đợi. Thông qua một số thử nghiệm và lỗi, và cuối cùng sử dụng Fiddler để đánh hơi lưu lượng truy cập thô, tôi phát hiện ra tiêu đề ủy quyền không được gửi đi.

Tôi đã xem this, nhưng tôi nghĩ rằng tôi đã có sơ đồ xác thực được chỉ định như một phần của hàm tạo AuthenticationHeaderValue.

Có điều gì tôi đã bỏ lỡ không?

Trả lời

25

Mã của bạn có vẻ như nó nên làm việc - Tôi nhớ chạy vào một vấn đề tương tự thiết lập các tiêu đề ủy quyền và giải quyết bằng cách làm một Headers.Add() thay vì đặt nó:

request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", "password")))); 

UPDATE: Dường như khi bạn thực hiện request.Content, không phải tất cả các tiêu đề đều được phản ánh trong đối tượng nội dung. Bạn có thể thấy điều này bằng cách kiểm tra request.Headers vs request.Content.Headers. Một điều bạn có thể muốn thử là sử dụng SendAsync thay vì PostAsync. Ví dụ:

HttpRequestMessage<RequestType> request = 
    new HttpRequestMessage<RequestType>(
     new RequestType("third-party-vendor-action"), 
     MediaTypeHeaderValue.Parse("application/xml")); 

request.Headers.Authorization = 
    new AuthenticationHeaderValue(
     "Basic", 
     Convert.ToBase64String(
      System.Text.ASCIIEncoding.ASCII.GetBytes(
       string.Format("{0}:{1}", "username", "password")))); 

request.Method = HttpMethod.Post; 
request.RequestUri = Uri; 
var task = client.SendAsync(request); 

ResponseType response = task.ContinueWith(
    t => 
     { return t.Result.Content.ReadAsAsync<ResponseType>(); }) 
     .Unwrap().Result; 
+0

Tôi đã thử điều đó và điều gì đó tương tự với 'request.Headers.Authorization' với cùng kết quả. Nó để lại cho tôi với một chút của một scratcher đầu như tôi không hoàn toàn chắc chắn những gì để thử tiếp theo. Tôi biết bản xem trước MVC4 beta và 4.5 trực tiếp không tương thích với một số thứ - tôi tự hỏi liệu điều đó có liên quan gì đến nó không? – Ross

+0

Bản cập nhật của bạn dường như ít nhất gửi tiêu đề ủy quyền. Tôi chưa thể truy xuất dữ liệu từ dịch vụ của bên thứ ba (có thể có điều gì đó không đúng trong phần yêu cầu mà tôi đã bỏ lỡ), nhưng ít nhất các tiêu đề chính xác đang đi qua dây. Đó là một sự khởi đầu. Cảm ơn bạn! – Ross

+0

ASCII hoặc UTF-8? Xem http://stackoverflow.com/questions/11743160/how-do-i-encode-and-decode-a-base64-string. – Philippe

17

Cố gắng thiết lập các tiêu đề trên máy khách:

DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password)))); 

này làm việc cho tôi.

+1

Điều này có thể hoạt động, nhưng nó sẽ đặt tiêu đề ủy quyền cho tất cả các yêu cầu, phải không? Đó không phải là mong muốn. – Ross

+2

Đối với tất cả các yêu cầu được thực hiện với trường hợp đó của một khách hàng, có. Bạn có đang sử dụng cùng một máy khách để truy cập các điểm cuối với các lược đồ xác thực khác nhau không? Tức là, bạn có đang thiết lập BaseAddress trên cá thể máy khách hay không? –

15

Điều này cũng sẽ làm việc và bạn sẽ không phải đối phó với các chuyển đổi chuỗi base64:

var handler = new HttpClientHandler(); 
handler.Credentials = new System.Net.NetworkCredential("username", "password"); 
var client = new HttpClient(handler); 
... 
+0

giải pháp sạch hơn nhiều so với mã hóa kết hợp UID: PWD. –

2

Thực ra vấn đề của bạn là với PostAsync - bạn nên sử dụng SendAsync. Trong mã của bạn - client.PostAsync(Uri, request.Content); chỉ gửi nội dung mà tiêu đề thư yêu cầu không được bao gồm. Cách thích hợp là:

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url) 
{ 
    Content = content 
}; 
message.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials); 
httpClient.SendAsync(message); 
+0

Một nghìn lần cảm ơn bạn. Tôi đã dành nhiều giờ cố gắng để đính kèm tiêu đề cho HttpClient và sử dụng GetAsync và PostAsync vv, và nói chung đang tìm thấy WebAPI một nỗi đau (cho tôi ServiceStack !!) –

Các vấn đề liên quan