10

我正在开发一个 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;
}

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

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

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

4

4 回答 4

9

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

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

在服务器端检索它

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

我还建议您查看以下文章:

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

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

于 2013-01-31T08:58:49.453 回答
4

如果您的 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;
    }
于 2013-01-31T09:31:58.717 回答
2

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()
    
于 2015-01-22T20:40:53.760 回答
0

您的解决方案的问题是它会添加一个 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);
}
于 2014-11-26T09:40:22.133 回答