2009-05-22 8 views
40

Tôi đang cố gắng viết một trình khách dịch vụ web bằng C# webservice là Java Axis 1.4. Dịch vụ trục yêu cầu giá trị tiêu đề Cấp phép: Cơ bản Base64EncodedToken trong Tiêu đề HTTP. Tôi không thể tìm cách thiết lập tiêu đề này theo các cách thức tiêu dùng nhất trong việc tiêu thụ các dịch vụ web trong studio.net trực quan, như giới thiệu WSDL bình thường cũng như với WSE3.0Cách thêm Tiêu đề Http tùy chỉnh cho Dịch vụ Web C# Khách hàng tiêu thụ dịch vụ Web 1.4 Axis

Tôi không thể sử dụng WCF khi dự án được phát triển sử dụng .net 2.0.

Có cách nào để thực hiện việc này không?

Trả lời

7

Nếu bạn muốn gửi một HTTP tùy chỉnh Header (không phải là một SOAP Header) thì bạn cần phải sử dụng lớp HttpWebRequest mã sẽ trông như thế:

HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); 
webRequest.Headers.Add("Authorization", token); 

Bạn không thể thêm tiêu đề HTTP sử dụng visual studio tạo proxy, có thể là một nỗi đau thực sự.

+0

"Bạn không thể thêm tiêu đề HTTP sử dụng visual studio proxy tạo ra" đây có phải là vẫn còn trường hợp? – chaostheory

+0

Tôi có thể thêm các tiêu đề như thế này nhưng làm cách nào để đưa chúng trở lại trong Dịch vụ WCF? – Joshy

24

Chúng ta có đang nói WCF ở đây không? Tôi gặp sự cố khi các cuộc gọi dịch vụ không thêm tiêu đề ủy quyền http, bao gồm mọi lời gọi vào tuyên bố này đã khắc phục được sự cố của tôi.

using (OperationContextScope scope = new OperationContextScope(RefundClient.InnerChannel)) 
    { 
      var httpRequestProperty = new HttpRequestMessageProperty(); 
      httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + 
      Convert.ToBase64String(Encoding.ASCII.GetBytes(RefundClient.ClientCredentials.UserName.UserName + ":" + 
      RefundClient.ClientCredentials.UserName.Password)); 
      OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty; 

      PaymentResponse = RefundClient.Payment(PaymentRequest); 
    } 

Điều này đang chạy các cuộc gọi SOAP đến IBM ESB qua .NET với xác thực cơ bản qua http hoặc https.

Tôi hy vọng điều này sẽ giúp một người nào đó ra vì tôi có vấn đề lớn khi tìm giải pháp trực tuyến.

+2

Đây thực sự là vấn đề của tôi. Bằng cách nào đó khi bạn đặt thông tin xác thực trong proxy, nó không hoạt động. Cảm ơn! – Tawani

+0

Tôi đang sử dụng WCF/Xà phòng, vì vậy điều này làm việc thực sự tốt cho tôi. Trong trường hợp của tôi, tôi cần một tiêu đề tùy chỉnh có tên "Auth-Token". Vì vậy, tôi (VB.NET) mã đã được -> httpRequestProperty.Headers.Add ("Auth-Token", "xxxxx") – robnick

+0

Điều này giải quyết vấn đề của tôi cũng có. Tôi đã có cùng một vấn đề như Tawani, khi tôi thiết lập các thông tin đăng nhập thông qua proxy tôi đã trở lại 401. Nhưng với mã của bạn tất cả mọi thứ hoạt động hoàn hảo! Cảm ơn nhiều! – merger

40

Dường như tác giả ban đầu đã tìm thấy giải pháp của họ, nhưng đối với bất kỳ ai khác được đây tìm cách để thêm tiêu đề tùy chỉnh thực tế, nếu bạn có quyền truy cập để mod mã Nghị định thư được tạo ra, bạn có thể ghi đè lên GetWebRequest:

protected override System.Net.WebRequest GetWebRequest(Uri uri) 
{ 
    System.Net.WebRequest request = base.GetWebRequest(uri); 
    request.Headers.Add("myheader", "myheader_value"); 
    return request; 
} 

Đảm bảo bạn xóa thuộc tính DebuggerStepThroughAttribute nếu bạn muốn tham gia.

+0

Đây chính xác là những gì tôi cần. Dịch vụ Web đã trả về 500 thay vì 401 cho Không được ủy quyền, vì vậy thông tin đăng nhập không bao giờ được gửi bằng cách sử dụng phương pháp tiếp cận trong câu trả lời được chấp nhận. Trong khi tôi cảm thấy bẩn mã sửa đổi được tạo ra, điều này cho phép tôi buộc gửi chúng với yêu cầu đầu tiên. Xem http://www.west-wind.com/weblog/posts/243915.aspx. –

+2

Hey, có vẻ như chính xác những gì tôi cần. nhưng tôi nên đặt chức năng này ở đâu? –

+0

nhưng không thể thêm tiêu đề có nhiều giá trị được phân cách bằng dấu phẩy trong phần giá trị cho tiêu đề bạn đang thêm? Điều đó cũng rất quan trọng cần biết như đối với các tham số ủy quyền OAuth – PositiveGuy

4

Tôi tìm thấy mã này và giải quyết được sự cố của mình.

http://arcware.net/setting-http-header-authorization-for-web-services/

protected override WebRequest GetWebRequest(Uri uri) 
{ 
    // Assuming authValue is set from somewhere, such as the config file 
    HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri); 
    request.Headers.Add("Authorization", string.Format("Basic {0}", authValue)); 
    return request; 
} 
+2

Hey, có vẻ như chính xác những gì tôi cần. nhưng tôi nên đặt chức năng này ở đâu? –

+1

Tôi cũng không biết đặt nó ở đâu và tôi đang sử dụng .net 4.0. Dịch vụ của tôi được tạo ra khác với các ví dụ khác mà tôi tìm thấy –

0

Đây là những gì làm việc cho tôi:

protected override System.Net.WebRequest GetWebRequest(Uri uri) 
{ 
     HttpWebRequest request; 
     request = (HttpWebRequest)base.GetWebRequest(uri); 
     NetworkCredential networkCredentials = 
     Credentials.GetCredential(uri, "Basic"); 
     if (networkCredentials != null) 
     { 
      byte[] credentialBuffer = new UTF8Encoding().GetBytes(
      networkCredentials.UserName + ":" + 
      networkCredentials.Password); 
      request.Headers["Authorization"] = 
      "Basic " + Convert.ToBase64String(credentialBuffer); 
      request.Headers["Cookie"] = "BCSI-CS-2rtyueru7546356=1"; 
      request.Headers["Cookie2"] = "$Version=1"; 
     } 
     else 
     { 
      throw new ApplicationException("No network credentials"); 
     } 
     return request; 
} 

Đừng quên để thiết lập thuộc tính này:

service.Credentials = new NetworkCredential("username", "password"); 

Cookie và Cookie2 được thiết lập trong phần đầu vì dịch vụ java không chấp nhận yêu cầu và tôi đã nhận được lỗi trái phép.

+0

Tôi đã loại bỏ quá tải ở trên và chỉ mã này thực hiện tất cả các phép thuật: serviceClient.CookieContainer = new CookieContainer(); –

3

Thay vì modding mã tự động tạo ra hoặc gói mỗi cuộc gọi trong mã trùng lặp, bạn có thể tiêm header HTTP tùy chỉnh của bạn bằng cách thêm một thanh tra viên thông báo tùy chỉnh, nó dễ dàng hơn so với âm thanh:

public class CustomMessageInspector : IClientMessageInspector 
{ 
    readonly string _authToken; 

    public CustomMessageInspector(string authToken) 
    { 
     _authToken = authToken; 
    } 

    public object BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 
     var reqMsgProperty = new HttpRequestMessageProperty(); 
     reqMsgProperty.Headers.Add("Auth-Token", _authToken); 
     request.Properties[HttpRequestMessageProperty.Name] = reqMsgProperty; 
     return null; 
    } 

    public void AfterReceiveReply(ref Message reply, object correlationState) 
    { } 
} 


public class CustomAuthenticationBehaviour : IEndpointBehavior 
{ 
    readonly string _authToken; 

    public CustomAuthenticationBehaviour (string authToken) 
    { 
     _authToken = authToken; 
    } 
    public void Validate(ServiceEndpoint endpoint) 
    { } 

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { } 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
    { } 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
     clientRuntime.ClientMessageInspectors.Add(new CustomMessageInspector(_authToken)); 
    } 
} 

Và khi instantiating lớp khách hàng của bạn, bạn có thể chỉ cần thêm nó dưới dạng hành vi:

this.Endpoint.EndpointBehaviors.Add(new CustomAuthenticationBehaviour("Auth Token")); 

Điều này sẽ làm cho mọi cuộc gọi dịch vụ đi có tiêu đề HTTP tùy chỉnh của bạn.

+1

Saeb Amini, cảm ơn bạn. Đây là câu trả lời tôi đang tìm kiếm để giải quyết vấn đề của tôi bằng dịch vụ web của bên thứ ba đã thay đổi thành xác thực 2 yếu tố. API của họ được cung cấp cho chúng tôi bởi XSD và WSDL mà chúng tôi đã tạo mã khách hàng thông qua chương trình svcutil. Sử dụng mã ở trên cho phép tôi thêm hành vi để chèn tiêu đề HTTP bằng mã thông báo để thực hiện xác thực 2 yếu tố. Cảm ơn một lần nữa! – bolski

1

câu trả lời của người dùng334291 là một trình tiết kiệm cuộc sống cho tôi. Chỉ muốn thêm làm thế nào bạn có thể thêm những gì OP ban đầu dự định làm (những gì tôi đã kết thúc sử dụng):

Trọng chức năng GetWebRequest trên mã webservice tạo:

protected override System.Net.WebRequest GetWebRequest(Uri uri) 
{ 
    System.Net.WebRequest request = base.GetWebRequest(uri);   
    string auth = "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(this.Credentials.GetCredential(uri, "Basic").UserName + ":" + this.Credentials.GetCredential(uri, "Basic").Password)); 
    request.Headers.Add("Authorization", auth); 
    return request; 
} 

và thiết lập các thông tin trước khi gọi webservice:

client.Credentials = new NetworkCredential(user, password);