简体   繁体   English

如何为使用Axis 1.4 Web服务的C#Web服务客户端添加自定义Http Header

[英]How to add custom Http Header for C# Web Service Client consuming Axis 1.4 Web service

I'm trying to write a web service client in c# which the webservice is Java Axis 1.4. 我正在尝试在c#中编写一个Web服务客户端,其Web服务是Java Axis 1.4。 Axis service requires the Authorization: Basic Base64EncodedToken header value in the HTTP Headers. Axis服务需要HTTP标头中的Authorization:Basic Base64EncodedToken标头值。 I can't find a way to set this header in standart ways of consuming web services in visual studio.net, like normal WSDL generated refernce nor with WSE3.0 我找不到一种方法来在visual studio.net中以不同的方式设置这个头文件,就像普通的WSDL生成引用一样,也不是WSE3.0

I can't use WCF as the project is developed using .net 2.0. 我不能使用WCF,因为项目是使用.net 2.0开发的。

Is there any way to do this ? 有没有办法做到这一点?

It seems the original author has found their solution, but for anyone else who gets here looking to add actual custom headers, if you have access to mod the generated Protocol code you can override GetWebRequest : 原作者似乎找到了他们的解决方案,但对于其他任何想要添加实际自定义标头的人来说,如果您有权访问mod生成的协议代码,则可以覆盖GetWebRequest

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

Make sure you remove the DebuggerStepThroughAttribute attribute if you want to step into it. 如果要进入,请确保删除DebuggerStepThroughAttribute属性。

Are we talking WCF here? 我们在这里谈论WCF吗? I had issues where the service calls were not adding the http authorization headers, wrapping any calls into this statement fixed my issue. 我遇到的问题是服务调用没有添加http授权头,将任何调用包装到此语句中解决了我的问题。

  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);
   }

This was running SOAP calls to IBM ESB via .NET with basic auth over http or https. 这是通过.NET运行对IBM ESB的SOAP调用,通过http或https进行基本身份验证。

I hope this helps someone out because I had massive issues finding a solution online. 我希望这可以帮助别人,因为我在网上找到解决方案时遇到了大量问题。

Instead of modding the auto-generated code or wrapping every call in duplicate code, you can inject your custom HTTP headers by adding a custom message inspector, it's easier than it sounds: 您可以通过添加自定义消息检查器来注入自定义HTTP标头,而不是修改自动生成的代码或将每个调用包装在重复的代码中,它比听起来更容易:

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));
    }
}

And when instantiating your client class you can simply add it as a behavior: 在实例化您的客户端类时,您只需将其添加为行为:

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

This will make every outgoing service call to have your custom HTTP header. 这将使每个传出服务调用都具有您的自定义HTTP标头。

If you want to send a custom HTTP Header (not a SOAP Header) then you need to use the HttpWebRequest class the code would look like: 如果要发送自定义HTTP标头(而不是SOAP标头),则需要使用代码如下的HttpWebRequest类:

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

You cannot add HTTP headers using the visual studio generated proxy, which can be a real pain. 您无法使用visual studio生成的代理添加HTTP标头,这可能是一个真正的痛苦。

I find this code and is resolve my problem. 我找到这个代码并解决了我的问题。

http://arcware.net/setting-http-header-authorization-for-web-services/ 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;
}

user334291's answer was a life saver for me. user334291的答案对我来说是一个救生员。 Just want to add how you can add what the OP originally intended to do (what I ended up using): 只想添加如何添加OP原本打算做的事情(我最终使用的内容):

Overriding the GetWebRequest function on the generated webservice code: 覆盖生成的Web服务代码上的GetWebRequest函数:

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;
}

and setting the credentials before calling the webservice: 并在调用webservice之前设置凭据:

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

Here is what worked for me: 这对我有用:

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;
}

Don't forget to set this property: 别忘了设置这个属性:

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

Cookie and Cookie2 are set in header because java service was not accepting the request and I was getting Unauthorized error. Cookie和Cookie2在标头中设置,因为java服务不接受请求,我收到了Unauthorized错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM