53

我正在尝试用 c# 编写一个 Web 服务客户端,该 Web 服务是 Java Axis 1.4。Axis 服务需要 HTTP 标头中的Authorization: Basic Base64EncodedToken标头值。我找不到以标准方式在 Visual Studio.net 中使用 Web 服务的标准方式设置此标头的方法,例如普通 WSDL 生成的引用或 WSE3.0

我不能使用 WCF,因为该项目是使用 .net 2.0 开发的。

有没有办法做到这一点?

4

7 回答 7

52

似乎原作者已经找到了他们的解决方案,但是对于任何到这里来希望添加实际自定义标头的人来说,如果您有权访问 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;
}

DebuggerStepThroughAttribute如果要进入该属性,请确保删除该属性。

于 2010-05-06T10:08:45.220 回答
27

我们在这里谈论 WCF 吗?我遇到了服务调用未添加 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);
   }

这是通过 .NET 使用 http 或 https 上的基本身份验证运行对 IBM ESB 的 SOAP 调用。

我希望这对某人有所帮助,因为我在网上寻找解决方案时遇到了很多问题。

于 2009-11-11T03:21:55.273 回答
17

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:

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.

于 2017-03-06T01:55:38.483 回答
7

如果要发送自定义 HTTP 标头(不是 SOAP 标头),则需要使用 HttpWebRequest 类,代码如下所示:

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

您不能使用 Visual Studio 生成的代理添加 HTTP 标头,这可能会很痛苦。

于 2009-05-22T13:43:19.047 回答
5

我找到了这段代码并解决了我的问题。

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;
}
于 2010-08-10T21:48:52.507 回答
1

user334291's answer was a life saver for me. Just want to add how you can add what the OP originally intended to do (what I ended up using):

Overriding the GetWebRequest function on the generated webservice code:

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:

  client.Credentials = new NetworkCredential(user, password);       
于 2018-02-19T16:11:59.623 回答
0

这对我有用:

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

不要忘记设置此属性:

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.

于 2013-08-01T23:14:04.297 回答