Search code examples
c#wcf

Visual Studio host , The authentication schemes configured on the host ('Anonymous')


i faced and error

The authentication schemes configured on the host ('Anonymous') do not allow those configured on the binding 'WebHttpBinding' ('Basic').

The problem occur when i run the Service in VS.

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.6" />
    <httpRuntime targetFramework="4.6"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding>
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Basic" />
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceX_Behavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ServiceX.CustomUserNamePasswordValidator, ServiceX"/>
          </serviceCredentials>
          <!--<serviceAuthenticationManager authenticationSchemes="Basic"/>-->
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="webHttpBinding_Behavior">
          <webHttp helpEnabled="true"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <!--<protocolMapping>
      <add binding="basicHttpBinding" scheme="http" />
    </protocolMapping>-->
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
      <service name="ServiceX.ServiceX" behaviorConfiguration="ServiceX_Behavior">
        <endpoint address="" binding="webHttpBinding" contract="ServiceX.IServiceX" behaviorConfiguration="webHttpBinding_Behavior" />
        <endpoint address="soap" binding="basicHttpBinding" contract="ServiceX.IServiceX" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

When i run in IIS , it workk fine. When i run in Console app , it works fun. What is the difference with VS ? the following work fine, the same as config described above

Uri serviceUri = new Uri("http://localhost/TestService");
ServiceHost serviceHost = new ServiceHost(typeof(TestService), serviceUri);


BasicHttpBinding basicHttp = new BasicHttpBinding();
serviceHost.AddServiceEndpoint(typeof(IService), basicHttp, "soap");

ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
serviceHost.Description.Behaviors.Add(behavior);
serviceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");


var contract = ContractDescription.GetContract(typeof(IService));
contract.Namespace = "WCFServer";

var webHttpEndpoint = new WebHttpEndpoint(contract);
webHttpEndpoint.Address = new EndpointAddress(serviceUri);
var webHttpBinding = (WebHttpBinding)webHttpEndpoint.Binding;
webHttpBinding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
webHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
serviceHost.AddServiceEndpoint(webHttpEndpoint);

//serviceHost.Authentication.AuthenticationSchemes = AuthenticationSchemes.Basic;
serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameAuthentication();

foreach (var bh in serviceHost.Description.Behaviors)
{
    var serviceMetadata = bh as ServiceMetadataBehavior;
    if (serviceMetadata != null)
    {
        serviceMetadata.HttpGetEnabled = true;
    }

    var serviceDebug = bh as ServiceDebugBehavior;
    if (serviceDebug != null)
    {
        serviceDebug.IncludeExceptionDetailInFaults = false;
    }
}
serviceHost.Open();
Console.ReadLine();
serviceHost.Close();

In ISS Basic Authentication and Anonymous Authentication are allowed
IN VS Anonymous Authentication enabled

How come in Visual Studio the WCF web project doesn't work , Console project and deployed in IIS web app work fine. What is the difference ?

I want to implement Basic Authentication in WCF


Solution

  • The root cause is that IIS Express hasn't enabled the BasicAuthentication by default. As you know we need to enable BasicAuthentication to support WCF BasicAuthentication. IIS Express is configured with the ApplicationHost.config file. We should update the following values in the ApplicationHost.config to enable BasicAuthentication.

    <security>
                <access sslFlags="None" />
                <applicationDependencies>
                    <application name="Active Server Pages" groupId="ASP" />
                </applicationDependencies>
                <authentication>
                    <anonymousAuthentication enabled="true" userName="" />
    <!-- set to true –->
                    <basicAuthentication enabled="true" />
    

    In VS2015 and above. The ApplicationHost.config locates in the below.

    Solution file directory(containing the Sln file)/.vs/solution name/applicationhost.config

    Feel free to let me know if the problem still exists.