WCF security with Certificates

7

Good I am trying to connect a WCF service with security through certificates, in the development environment it works correctly, in a simulated environment with 2 teams, one as a service and another as a client, or in the same team (service and client) the connection is made correctly, these computers are in windows 10. When you publish it to the production server, Windows 2012 r2 with iis 8.5, you have an error in the client:

  

The caller was not authenticated by the service. The request for security token could not be satisfied because authentication failed.   The communication object, System.ServiceModel.Channels.ServiceChannel, can not be used for communication because it is in the Faulted state.

I made a simple console these are the data For certificates use the instructions in this post

cliente.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cliente
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("-------------------------------------");
try
            {
                using (ServerSinSeguridad.ServicioSinSeguridadClient sinSeguridad = new ServerSinSeguridad.ServicioSinSeguridadClient())
                {
                    Console.WriteLine(sinSeguridad.MostrarDatos("Sin Seguridad"));

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                if (ex.InnerException != null)
                    Console.WriteLine(ex.InnerException.Message);
            }
            Console.WriteLine("-------------------------------------");
            try
            {
                using (ServerConSeguridad.ServicioConSeguridadClient sinSeguridad = new ServerConSeguridad.ServicioConSeguridadClient())
                {
                    Console.WriteLine(sinSeguridad.MostrarDatos("Con Seguridad"));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                if (ex.InnerException != null)
                    Console.WriteLine(ex.InnerException.Message);
            }
            Console.WriteLine("-------------------------------------");
            try
            {
                using (WSIIsSeguridad.Service1Client sinSeguridad = new WSIIsSeguridad.Service1Client())
                {
                    var c = sinSeguridad.ChannelFactory.CreateChannel();
                    try
                    {
                        Console.WriteLine(c.GetData(123));
                    }
                    catch (Exception we)
                    {
                        Console.WriteLine(we.Message);
                        if (we.InnerException != null)
                            Console.WriteLine(we.InnerException.Message);
                    }

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                if (ex.InnerException != null)
                    Console.WriteLine(ex.InnerException.Message);
            }
            Console.Read();
        }
    }
}

client.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="SinSeguridad" />
      </basicHttpBinding>
      <wsHttpBinding>
        <binding name="ConSeguridad">
          <security mode="Message">
            <message clientCredentialType="Certificate" />
          </security>
        </binding>
        <binding name="ConSeguridad1">
          <security mode="Message">
            <message clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ConSeguridad">
          <clientCredentials>
            <clientCertificate findValue="CN=tempCertCliente"/>
          </clientCredentials>
        </behavior>
        <behavior name="ConSeguridad1">
          <clientCredentials>
            <clientCertificate findValue="CN=tempCertCliente"/>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <client>
      <endpoint address="http://localhost:8733/SinSeguridadServicio/"
        binding="basicHttpBinding" bindingConfiguration="SinSeguridad"
        contract="ServerSinSeguridad.IServicioSinSeguridad" name="SinSeguridad" />
      <endpoint address="http://localhost:8732/ConSeguridadServicio/"
        behaviorConfiguration="ConSeguridad" binding="wsHttpBinding"
        bindingConfiguration="ConSeguridad" contract="ServerConSeguridad.IServicioConSeguridad"
        name="ConSeguridad">
        <identity>
          <certificateReference storeName="My" storeLocation="LocalMachine"
            x509FindType="FindBySubjectDistinguishedName" findValue="CN=tempCertService" />
        </identity>
      </endpoint>
      <endpoint address="http://localhost:50873/Service1.svc" binding="wsHttpBinding"
                behaviorConfiguration="ConSeguridad1"
        bindingConfiguration="ConSeguridad1" contract="WSIIsSeguridad.IService1"
        name="ConSeguridad1">
        <identity>
          <certificateReference storeName="My" storeLocation="LocalMachine"
            x509FindType="FindBySubjectDistinguishedName" findValue="CN=tempCertService" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

self-hosted service

program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace ServicioWcf
{
    public class ServicioConSeguridad : IServicioConSeguridad
    {
        public string MostrarDatos(string dato)
        {
            Console.WriteLine(dato);
            return $"Recibido {DateTime.Now}";
        }
    }

    public class ServicioSinSeguridad : IServicioSinSeguridad
    {
        public string MostrarDatos(string dato)
        {
            Console.WriteLine(dato);
            return $"Recibido {DateTime.Now}";
        }
    }

    [ServiceContract]
    public interface IServicioConSeguridad
    {
        [OperationContract]
        string MostrarDatos(string dato);
    }

    [ServiceContract]
    public interface IServicioSinSeguridad
    {
        [OperationContract]
        string MostrarDatos(string dato);
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (ServiceHost sinSeguridad = new ServiceHost(typeof(ServicioSinSeguridad)))
                {
                    using (ServiceHost conSeguridad = new ServiceHost(typeof(ServicioConSeguridad)))
                    {

                        sinSeguridad.Faulted += serviceHost_Faulted;
                        sinSeguridad.UnknownMessageReceived += serviceHost_UnknownMessageReceived;
                        sinSeguridad.Open();


                        conSeguridad.Faulted += serviceHost_Faulted;
                        conSeguridad.UnknownMessageReceived += serviceHost_UnknownMessageReceived;
                        conSeguridad.Open();

                        Console.WriteLine("Listo, Escuchando");
                        Console.Read();
                    }
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                if (ex.InnerException != null)
                    Console.WriteLine(ex.InnerException.Message);
            }
            Console.Read();
        }
        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is Exception)
                Console.WriteLine(((Exception)e.ExceptionObject).Message);
            else
                Console.WriteLine(e.ExceptionObject.ToString());
        }
        static void Build(ref ServiceHost serviceHost, Type service)
        {

            if (serviceHost != null)
            {
                serviceHost.Close();
            }
            // Create a ServiceHost for the CalculatorService type and 
            // provide the base address.
            serviceHost = new ServiceHost(service);

            // Open the ServiceHostBase to create listeners and start 
            // listening for messages.
            serviceHost.Open();
            serviceHost.Faulted += serviceHost_Faulted;
            serviceHost.UnknownMessageReceived += serviceHost_UnknownMessageReceived;

        }
        static void serviceHost_Faulted(object sender, EventArgs e)
        {

        }
        static void serviceHost_UnknownMessageReceived(object sender, UnknownMessageReceivedEventArgs e)
        {
            Console.WriteLine(e.Message.ToString());
        }

    }
}

servicio.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServicioSinSeguridad">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
        </behavior>
        <behavior name="ServicioConSeguridad">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
          <serviceCredentials>
            <serviceCertificate findValue="CN=tempCertService" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="ServicioSinSeguridad" name="ServicioWcf.ServicioSinSeguridad">
        <endpoint address="" binding="basicHttpBinding" 
          name="SinSeguridad" contract="ServicioWcf.IServicioSinSeguridad" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8733/SinSeguridadServicio/" />
          </baseAddresses>
        </host>
      </service>
      <service behaviorConfiguration="ServicioConSeguridad" name="ServicioWcf.ServicioConSeguridad">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSeguridad"
          name="ConSeguridad" contract="ServicioWcf.IServicioConSeguridad" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8732/ConSeguridadServicio/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpEndpointBindingSeguridad">
          <security mode="Message">
            <message clientCredentialType="Certificate" negotiateServiceCredential="true" establishSecurityContext="true" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>
</configuration>

service hosted in the IIS

WcfServiceIIS.svc

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfServiceIIS
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract(Namespace = "Esta.Es.Para.Vos")]
    public interface IService1
    {

        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        // TODO: Add your service operations here
    }


    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }

    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

web.config

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

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServicioConSeguridad">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
          <serviceCredentials>
            <clientCertificate>
              <certificate storeLocation="LocalMachine" storeName="My" findValue="CN=tempCertCliente" x509FindType="FindBySubjectDistinguishedName"/>
            </clientCertificate>
            <serviceCertificate findValue="CN=tempCertService" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="ServicioConSeguridad"  name="WcfServiceIIS.Service1">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSeguridad" bindingNamespace="Esta.Es.Para.Vos"
          name="ConSeguridad" contract="WcfServiceIIS.IService1" >
          <identity>
            <certificateReference findValue="CN=tempCertService" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" />
          </identity>
        </endpoint>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpEndpointBindingSeguridad">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483646" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
          <security mode="Message">
            <message clientCredentialType="Certificate" negotiateServiceCredential="true" establishSecurityContext="true" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <!--<protocolMapping>
      <add binding="wsHttpBinding" scheme="https" />
    </protocolMapping>-->
    <!--<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />-->
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>
    
asked by Byron 16.11.2016 в 23:34
source

1 answer

0

Try placing this type of authentication on the web.with:

<serviceCredentials> 
  <windowsAuthentication allowAnonymousLogons="true"/> 
</serviceCredentials> 
    
answered by 20.12.2016 в 16:19