简体   繁体   中英

WCF REST Basic Authentication - not able to set authorization header

I have created a WCF REST service and I am trying to do custom authentication (as it should work on http and https).

I am using custome service authorization manager to check and validate authorization header.

When I call the service using Fiddler and pass Authorization header with request, I am receiving it correctly in the service authorization manager.

But when I am setting credentials on WCFChannelFactory, I am not receiving Authorization header in the service. I expect that authorization header should be created by WCFChannelFactory and passed with request.

Client code is as below:

WebChannelFactory<IDataService> factory = new WebChannelFactory<IDataService>("DataServiceClient1");
factory.Credentials.UserName.UserName = "user1";
factory.Credentials.UserName.Password = "password123";
var client = factory.CreateChannel();
var data = client.GetData1("Microsoft");
Console.WriteLine("Get response : {0}", data);

Client Service Configuration is as below:

  <system.serviceModel>
    <client>
      <endpoint address="http://localhost.fiddler:50179/DataService.svc"
                binding="webHttpBinding" bindingConfiguration="auth"
                contract="RESTWebServiceSpike.IDataService"
                behaviorConfiguration="web"
                name="DataServiceClient1">
      </endpoint>
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <webHttpBinding>
        <binding name="auth">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Basic" />
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
  </system.serviceModel>

My service Configuration is as below:

<services>
  <service name="RESTWebServiceSpike.DataService" behaviorConfiguration="DataServiceBehaviour">
    <endpoint address="" binding="webHttpBinding"
              contract="RESTWebServiceSpike.IDataService" behaviorConfiguration="web">
    </endpoint>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="DataServiceBehaviour">
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/>
      <serviceAuthorization serviceAuthorizationManagerType="RESTWebServiceImpl.AuthorizationManager, RESTWebServiceImpl" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="web">
      <webHttp/>
    </behavior>
  </endpointBehaviors>
</behaviors>

I am using custome service authorization manager to check and validate authorization header.

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() 

For posterity, here is the solution I found to this problem:

First, take out your <service></service> tags in your client.

Then, you need to wrap your call to your service in an OperationContextScope, inside which you'll add the header. For example:

using (new OperationContextScope((IClientChannel)client))
{
   HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty();
   string credentials = string.Format("{0}:{1}", _username, _password);
   requestProperty.Headers["Authorization"] = string.Format("Basic {0}", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(credentials)));
   OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty;
   data = client.GetData1();
}

Here is an MSDN point of reference:

http://blogs.msdn.com/b/drnick/archive/2008/07/08/adding-headers-to-a-call-http-version.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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