【问题标题】:How to add custom Http Header for C# Web Service Client consuming Axis 1.4 Web service如何为使用 Axis 1.4 Web 服务的 C# Web 服务客户端添加自定义 Http 标头
【发布时间】:2010-10-28 05:18:16
【问题描述】:

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

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

有什么办法吗?

【问题讨论】:

    标签: c# web-services wsdl axis


    【解决方案1】:

    似乎原作者已经找到了他们的解决方案,但是对于其他想要添加实际自定义标头的人来说,如果您可以访问 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 属性。

    【讨论】:

    • 这正是我所需要的。 Web 服务为 Unauthorized 返回 500 而不是 401,因此从未使用已接受答案中的方法发送凭据。虽然我觉得修改生成的代码很脏,但这让我可以在第一个请求时强制发送它们。见west-wind.com/weblog/posts/243915.aspx
    • 嘿,这似乎正是我所需要的。但是我应该把这个功能放在哪里?
    • 但是标题添加不能在您要添加的标题的值部分中有多个逗号分隔的值吗?对于 OAuth 授权参数,了解这一点也非常重要
    • 我已经把它和“reference.cs”文件一起放在一个部分类中,这样如果重新生成它就不会丢失。
    • 我试过了,效果很好。只需创建一个与代理同名并在与 Web 服务客户端代理相同的命名空间下的部分类。并在该类中添加此方法。
    【解决方案2】:

    我们在这里谈论 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 调用。

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

    【讨论】:

    • 这实际上是我的问题。不知何故,当您在代理中设置凭据时,它不起作用。谢谢!
    • 我正在使用 WCF/Soap,所以这对我来说非常有效。就我而言,我需要一个名为“Auth-Token”的自定义标头。所以我的(VB.NET)代码是 --> httpRequestProperty.Headers.Add("Auth-Token", "xxxxx")
    • 这也解决了我的问题。我遇到了和 Tawani 一样的问题,当我通过代理设置凭据时,我得到了 401。但是使用您的代码,一切正常!非常感谢!
    • 太棒了!为我设置授权标头以包含不记名令牌。
    • Hmmm... 在调试器中运行良好,但部署到 Azure 后,“OperationContext.Current 的值不是此 OperationContextScope 安装的 OperationContext 值。”
    【解决方案3】:

    您可以通过添加自定义消息检查器来注入自定义 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));
        }
    }
    

    在实例化您的客户端类时,您可以简单地将其添加为行为:

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

    这将使每个传出服务调用都有您的自定义 HTTP 标头。

    【讨论】:

    • 赛博阿米尼,谢谢。这是我正在寻找使用已更改为 2 因素身份验证的 3rd 方 Web 服务来解决我的问题的答案。他们的 API 由 XSD 和 WSDL 提供给我们,我们通过 svcutil 程序生成客户端代码。使用上面的代码,我可以添加行为以注入带有令牌的 HTTP 标头来执行 2 因素身份验证。再次感谢!
    • @bolski 很高兴知道它对您有所帮助! :)
    • 我已经在上述解决方案中添加了我的标题,并且效果很好。我遇到了在 Soap 请求中添加安全标头的问题。谢谢!
    • 我将我的 .Net 框架代码移植到了 .Net Core,但我的 CustomBehavior 课程出现了问题。我所要做的就是删除一些在 .Net Core 中显然不需要的类继承。感谢您仅添加所需的代码!
    【解决方案4】:

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

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

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

    【讨论】:

    • “您不能使用Visual Studio 生成的代理添加HTTP 标头” 还是这样吗?
    • 我可以像这样添加标头,但我如何将它们恢复到 WCF 服务中?
    【解决方案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;
    }
    

    【讨论】:

    • 嘿,这似乎正是我所需要的。但是我应该把这个功能放在哪里?
    • 我也不知道把它放在哪里,我正在使用.net 4.0。我的服务生成方式与我发现的其他示例不同
    【解决方案6】:

    user334291 的回答对我来说是救命稻草。只想添加如何添加 OP 最初打算做的事情(我最终使用的):

    在生成的 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;
    }
    

    并在调用网络服务之前设置凭据:

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

    【讨论】:

      【解决方案7】:

      这对我有用:

      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 和 Cookie2 设置在标头中,因为 java 服务不接受请求,我收到未经授权的错误。

      【讨论】:

      • 我摆脱了上面的重载,只有这段代码才能发挥作用:serviceClient.CookieContainer = new CookieContainer();
      猜你喜欢
      • 2013-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多