C# 如何向 WCF 中的请求添加授权标头?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14621544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 12:27:31  来源:igfitidea点击:

How can I add authorization header to the request in WCF?

c#winformswcfheader

提问by umais

I'm working on a Windows Form application and there's a WCF service that needs to be called. I need to add a header (authorization - custom) to the request before it's sent to the service. I have a custom inspector class as well. I tried the following but the service is not called, somehow, and it returns an exception.

我正在处理一个 Windows 窗体应用程序,并且需要调用一个 WCF 服务。在将请求发送到服务之前,我需要向请求添加标头(授权 - 自定义)。我也有一个自定义检查器类。我尝试了以下操作,但以某种方式没有调用该服务,并且它返回一个异常。

public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
    MessageHeader header = MessageHeader.CreateHeader("Authorization", "", "Basic Y19udGk6Q29udGlfQjNTVA==");
    OperationContext.Current.OutgoingMessageHeaders.Add(header);
    HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
    httpRequestProperty.Headers.Add("Authorization", "Basic Y19udGk6Q29udGlfQjNTVA==");
    httpRequestProperty.Headers.Add(HttpRequestHeader.UserAgent, "Continental");
            OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
    sentMessages.Add(request.ToString());
    return null;
}

I also tried simplest way like this one:

我也尝试过像这样的最简单的方法:

MessageHeader header = MessageHeader.CreateHeader("Authorization", "", "Basic Y19udGk6Q29udGlfQjNTVA==");
request.Headers.Add(header);

but it's the same, authorization header is added but it does not reach the service, how can I know what header is received by the service? I used SOAP UI and service responds well when I add such a header manually in the request (before running).

但它是一样的,添加了授权标头但它没有到达服务,我怎么知道服务收到了什么标头?当我在请求中手动添加这样的标头时(在运行之前),我使用了 SOAP UI 并且服务响应良好。

回答by Srinivas

The simplest way is to add it on the client side:

最简单的方法是在客户端添加它

using (MyServ.ServiceClient proxy = new MyServ.ServiceClient())
{
     using (new System.ServiceModel.OperationContextScope(proxy.InnerChannel))
     {
         MessageHeader head = MessageHeader.CreateHeader("Authorization", "http://yournamespace.com/v1", data);
         OperationContext.Current.OutgoingMessageHeaders.Add(head);
     }
}

and retrieve it on the server side:

在服务器端检索它

string  auth = OperationContext.Current.IncomingMessageHeaders.
GetHeader<string>("Authorization", "http://mynamespace.com/v1");

I also suggest that you check these articles:

我还建议您查看这些文章:

Authorization Header is missing in Http request using WCF

使用 WCF 的 Http 请求中缺少授权标头

WCF Service with wsHttpBinding - Manipulating HTTP request headers

带有 wsHttpBinding 的 WCF 服务 - 操作 HTTP 请求标头

回答by Markus

If there's some problem with your BeforeSend method, this is how I implemented it when adding authentication to some webservice calls.

如果您的 BeforeSend 方法有问题,这就是我在向某些 Web 服务调用添加身份验证时实现它的方式。

private const string Authorization = "Authorization";
public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        object httpRequestMessageObject;
        if (request.Properties.TryGetValue(
            HttpRequestMessageProperty.Name, out httpRequestMessageObject))
        {
            var httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;

            if (string.IsNullOrWhiteSpace(httpRequestMessage.Headers[Authorization]))
            {
                httpRequestMessage.Headers[Authorization] = "Basic Y19udGk6Q29udGlfQjNTVA==";
            }
        }
        else
        {
            var httpRequestMessage = new HttpRequestMessageProperty();
            httpRequestMessage.Headers.Add(Authorization, "Basic Y19udGk6Q29udGlfQjNTVA==");

            request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
        }

        return null;
    }

回答by bertl

The problem with your solution is that it would add an HTTP header. What you need is a SOAP header, however. That could be done like this...

您的解决方案的问题在于它会添加一个 HTTP 标头。但是,您需要的是 SOAP 标头。可以这样做...

using(new OperationContextScope(client.InnerChannel)) 
{
    // Add a SOAP Header to an outgoing request
    MessageHeader aMessageHeader = MessageHeader.CreateHeader("UserInfo", "http://tempuri.org", userInfo);
    OperationContext.Current.OutgoingMessageHeaders.Add(aMessageHeader);
}

回答by Denis

I know this is late but I ran across this post so decided to fill this in, in case I ever need to remember this again. This worked for me:

我知道这已经晚了,但我偶然发现了这篇文章,所以决定填写它,以防我需要再次记住它。这对我有用:

  1. Create the Message Inspector:

    Public Class AuthenticationHeader
      Implements IClientMessageInspector
    
    Private itsUser As String
    Private itsPass As String
    
    Public Sub New(ByVal user As String, ByVal pass As String)
        itsUser = user
        itsPass = pass
    End Sub
    
    Public Sub AfterReceiveReply(ByRef reply As Message, correlationState As Object) Implements IClientMessageInspector.AfterReceiveReply
        Console.WriteLine("Received the following reply: '{0}'", reply.ToString())
    End Sub
    
    Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest
        Dim hrmp As HttpRequestMessageProperty = request.Properties("httpRequest")
        Dim encoded As String = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(itsUser + ":" + itsPass))
        hrmp.Headers.Add("Authorization", "Basic " + encoded)
        Return request
      End Function
    End Class
    
  2. Write the Behavior:

    Public Class AuthenticationHeaderBehavior
    Implements IEndpointBehavior
    
    Private ReadOnly itsUser As String
    Private ReadOnly itsPass As String
    
    Public Sub New(ByVal user As String, ByVal pass As String)
        MyBase.New()
        itsUser = user
        itsPass = pass
    End Sub
    
    Public Sub AddBindingParameters(endpoint As ServiceEndpoint, bindingParameters As BindingParameterCollection) Implements IEndpointBehavior.AddBindingParameters
    End Sub
    
    Public Sub ApplyClientBehavior(endpoint As ServiceEndpoint, clientRuntime As ClientRuntime) Implements IEndpointBehavior.ApplyClientBehavior
        clientRuntime.MessageInspectors.Add(New AuthenticationHeader(itsUser, itsPass))
    End Sub
    
    Public Sub ApplyDispatchBehavior(endpoint As ServiceEndpoint, endpointDispatcher As EndpointDispatcher) Implements IEndpointBehavior.ApplyDispatchBehavior
    End Sub
    
    Public Sub Validate(endpoint As ServiceEndpoint) Implements IEndpointBehavior.Validate
    End Sub
    End Class
    
  3. Add it to your endpoint:

      Dim binding As New WebHttpBinding(WebHttpSecurityMode.Transport)
      binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None
    
      ChlFactory = New WebChannelFactory(Of IMyServiceContract)(binding, New Uri(url))
      ChlFactory.Endpoint.Behaviors.Add(New WebHttpBehavior())
      ChlFactory.Endpoint.Behaviors.Add(New AuthenticationHeaderBehavior(user, pass))
      Channel = ChlFactory.CreateChannel()
    
  1. 创建消息检查器:

    Public Class AuthenticationHeader
      Implements IClientMessageInspector
    
    Private itsUser As String
    Private itsPass As String
    
    Public Sub New(ByVal user As String, ByVal pass As String)
        itsUser = user
        itsPass = pass
    End Sub
    
    Public Sub AfterReceiveReply(ByRef reply As Message, correlationState As Object) Implements IClientMessageInspector.AfterReceiveReply
        Console.WriteLine("Received the following reply: '{0}'", reply.ToString())
    End Sub
    
    Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest
        Dim hrmp As HttpRequestMessageProperty = request.Properties("httpRequest")
        Dim encoded As String = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(itsUser + ":" + itsPass))
        hrmp.Headers.Add("Authorization", "Basic " + encoded)
        Return request
      End Function
    End Class
    
  2. 编写行为:

    Public Class AuthenticationHeaderBehavior
    Implements IEndpointBehavior
    
    Private ReadOnly itsUser As String
    Private ReadOnly itsPass As String
    
    Public Sub New(ByVal user As String, ByVal pass As String)
        MyBase.New()
        itsUser = user
        itsPass = pass
    End Sub
    
    Public Sub AddBindingParameters(endpoint As ServiceEndpoint, bindingParameters As BindingParameterCollection) Implements IEndpointBehavior.AddBindingParameters
    End Sub
    
    Public Sub ApplyClientBehavior(endpoint As ServiceEndpoint, clientRuntime As ClientRuntime) Implements IEndpointBehavior.ApplyClientBehavior
        clientRuntime.MessageInspectors.Add(New AuthenticationHeader(itsUser, itsPass))
    End Sub
    
    Public Sub ApplyDispatchBehavior(endpoint As ServiceEndpoint, endpointDispatcher As EndpointDispatcher) Implements IEndpointBehavior.ApplyDispatchBehavior
    End Sub
    
    Public Sub Validate(endpoint As ServiceEndpoint) Implements IEndpointBehavior.Validate
    End Sub
    End Class
    
  3. 将其添加到您的端点:

      Dim binding As New WebHttpBinding(WebHttpSecurityMode.Transport)
      binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None
    
      ChlFactory = New WebChannelFactory(Of IMyServiceContract)(binding, New Uri(url))
      ChlFactory.Endpoint.Behaviors.Add(New WebHttpBehavior())
      ChlFactory.Endpoint.Behaviors.Add(New AuthenticationHeaderBehavior(user, pass))
      Channel = ChlFactory.CreateChannel()