Delen via


Berichtbeveiliging met een Windows-client zonder referentieonderhandeling

In het volgende scenario ziet u een WCF-client (Windows Communication Foundation) en -service die wordt beveiligd door het Kerberos-protocol.

Zowel de service als de client bevinden zich in hetzelfde domein of in dezelfde vertrouwde domeinen.

Notitie

Het verschil tussen dit scenario en berichtbeveiliging met een Windows-client is dat dit scenario niet onderhandelt over de servicereferentie bij de service voordat het toepassingsbericht wordt verzonden. Omdat hiervoor het Kerberos-protocol is vereist, is voor dit scenario ook een Windows-domeinomgeving vereist.

Berichtbeveiliging zonder referentieonderhandeling

Characteristic Beschrijving
Beveiligingsmodus Bericht
Interoperabiliteit Ja, WS-Security met compatibele kerberos-tokenprofielclients
Verificatie (server) Wederzijdse verificatie van de server en client
Verificatie (client) Wederzijdse verificatie van de server en client
Integriteit Ja
Vertrouwelijkheid Ja
Transport HTTP
Binding WSHttpBinding

Service

De volgende code en configuratie zijn bedoeld om onafhankelijk van elkaar te worden uitgevoerd. Voer een van de volgende stappen uit:

  • Maak een zelfstandige service met behulp van de code zonder configuratie.

  • Maak een service met behulp van de opgegeven configuratie, maar definieer geen eindpunten.

Code

Met de volgende code wordt een service-eindpunt gemaakt dat gebruikmaakt van berichtbeveiliging. De code schakelt de onderhandeling van servicereferenties uit en het instellen van een beveiliging contexttoken (SCT).

Notitie

Als u het Windows-referentietype zonder onderhandeling wilt gebruiken, moet het gebruikersaccount van de service toegang hebben tot de service-principal-naam (SPN) die is geregistreerd bij het Active Directory-domein. U kunt dit op twee manieren doen:

  1. Gebruik het NetworkService of LocalSystem account om uw service uit te voeren. Omdat deze accounts toegang hebben tot de computer-SPN die tot stand is gebracht wanneer de computer lid wordt van het Active Directory-domein, genereert WCF automatisch het juiste SPN-element in het eindpunt van de service in de metagegevens van de service (Web Services Description Language of WSDL).

  2. Gebruik een willekeurig Active Directory-domeinaccount om uw service uit te voeren. In dit geval moet u een SPN voor dat domeinaccount instellen. Een manier om dit te doen, is het gebruik van het hulpprogramma Setspn.exe hulpprogramma. Zodra de SPN is gemaakt voor het account van de service, configureert u WCF om die SPN te publiceren naar de clients van de service via de metagegevens (WSDL). Dit wordt gedaan door de eindpuntidentiteit in te stellen voor het weergegeven eindpunt, ofwel een toepassingsconfiguratiebestand of code. In het volgende voorbeeld wordt de identiteit programmatisch gepubliceerd.

Zie Kerberos Technical Supplement voor Windows voor meer informatie over SPN's, het Kerberos-protocol en Active Directory. Zie SecurityBindingElement Authentication Modes voor meer informatie over eindpuntidentiteiten.

// Create the service host.
ServiceHost myServiceHost = new ServiceHost(typeof(Calculator));

// Create the binding.
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType =
     MessageCredentialType.Windows;

// Disable credential negotiation and establishment of the
// security context.
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.EstablishSecurityContext = false;

// Create a URI for the endpoint address.
Uri httpUri = new Uri("http://localhost/Calculator");

// Create the EndpointAddress with the SPN for the Identity.
EndpointAddress ea = new EndpointAddress(httpUri,
    EndpointIdentity.CreateSpnIdentity("service_spn_name"));

// Get the contract from the ICalculator interface (not shown here).
// See the sample applications for an example of the ICalculator.
ContractDescription contract = ContractDescription.GetContract(
    typeof(ICalculator));

// Create a new ServiceEndpoint.
ServiceEndpoint se = new ServiceEndpoint(contract, binding, ea);

// Add the service endpoint to the service.
myServiceHost.Description.Endpoints.Add(se);

// Open the service.
myServiceHost.Open();
Console.WriteLine("Listening...");
Console.ReadLine();

// Close the service.
myServiceHost.Close();
' Create the service host.
Dim myServiceHost As New ServiceHost(GetType(ServiceModel.Calculator))

' Create the binding.
Dim binding As New WSHttpBinding()
binding.Security.Mode = SecurityMode.Message
binding.Security.Message.ClientCredentialType = _
   MessageCredentialType.Windows

' Disable credential negotiation and establishment of the
' security context.
binding.Security.Message.NegotiateServiceCredential = False
binding.Security.Message.EstablishSecurityContext = False

' Create a URI for the endpoint address.
Dim httpUri As New Uri("http://localhost/Calculator")

' Create the EndpointAddress with the SPN for the Identity.
Dim ea As New EndpointAddress(httpUri, _
EndpointIdentity.CreateSpnIdentity("service_spn_name"))

' Get the contract from the ICalculator interface (not shown here).
' See the sample applications for an example of the ICalculator.
Dim contract As ContractDescription = ContractDescription.GetContract(GetType(ICalculator))

' Create a new ServiceEndpoint.
Dim se As New ServiceEndpoint(contract, binding, ea)

' Add the service endpoint to the service.
myServiceHost.Description.Endpoints.Add(se)

' Open the service.
myServiceHost.Open()
Console.WriteLine("Listening...")
Console.ReadLine()

' Close the service.
myServiceHost.Close()

Configuratie

De volgende configuratie kan worden gebruikt in plaats van de code.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <behaviors />
    <services>
      <service behaviorConfiguration="" name="ServiceModel.Calculator">
        <endpoint address="http://localhost/Calculator"
                  binding="wsHttpBinding"
                  bindingConfiguration="KerberosBinding"
                  name="WSHttpBinding_ICalculator"
                  contract="ServiceModel.ICalculator"
                  listenUri="net.tcp://localhost/metadata" >
         <identity>
            <servicePrincipalName value="service_spn_name" />
         </identity>
        </endpoint>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="KerberosBinding">
          <security>
            <message negotiateServiceCredential="false"
                     establishSecurityContext="false" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client />
  </system.serviceModel>
</configuration>

Klant

De volgende code en configuratie zijn bedoeld om onafhankelijk van elkaar te worden uitgevoerd. Voer een van de volgende stappen uit:

  • Maak een zelfstandige client met behulp van de code (en clientcode).

  • Maak een client die geen eindpuntadressen definieert. Gebruik in plaats daarvan de clientconstructor die de configuratienaam als argument gebruikt. Voorbeeld:

    CalculatorClient cc = new CalculatorClient("EndpointConfigurationName");
    
    Dim cc As New CalculatorClient("EndpointConfigurationName")
    

Code

Met de volgende code wordt de client geconfigureerd. De beveiligingsmodus is ingesteld op Bericht en het clientreferentietype is ingesteld op Windows. Houd er rekening mee dat de NegotiateServiceCredential eigenschappen EstablishSecurityContext zijn ingesteld op false.

Notitie

Als u het Windows-referentietype zonder onderhandeling wilt gebruiken, moet de client worden geconfigureerd met de SPN van het account van de service voordat de communicatie met de service wordt uitgevoerd. De client gebruikt de SPN om het Kerberos-token op te halen om de communicatie met de service te verifiëren en te beveiligen. In het volgende voorbeeld ziet u hoe u de client configureert met de SPN van de service. Als u het hulpprogramma servicemodelmetagegevenshulpprogramma (Svcutil.exe) gebruikt om de client te genereren, wordt de SPN van de service automatisch doorgegeven aan de client vanuit de metagegevens van de service (WSDL), als de metagegevens van de service die informatie bevatten. Zie de sectie 'Service' verderop in dit onderwerp voor meer informatie over het configureren van de service voor het opnemen van de SPN in de metagegevens van de service.

Zie Kerberos Technical Supplement voor Windows voor meer informatie over SPN's, Kerberos en Active Directory. Zie het onderwerp SecurityBindingElement Authentication Modes voor meer informatie over eindpuntidentiteiten.

// Create the binding.
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
    MessageCredentialType.Windows;

// Disable credential negotiation and the establishment of
// a security context.
myBinding.Security.Message.NegotiateServiceCredential = false;
myBinding.Security.Message.EstablishSecurityContext = false;

// Create the endpoint address and set the SPN identity.
// The SPN must match the identity of the service's SPN.
// If using SvcUtil to generate a configuration file, the SPN
// will be published as the <servicePrincipalName> element under the
// <identity> element.
EndpointAddress ea = new EndpointAddress(
new Uri("http://machineName/Calculator"),
EndpointIdentity.CreateSpnIdentity("service_spn_name"));

// Create the client.
CalculatorClient cc =
    new CalculatorClient(myBinding, ea);

// Begin using the client.

try
{
    cc.Open();
    Console.WriteLine(cc.Add(200, 1111));
    Console.ReadLine();

    // Close the client.
    cc.Close();
}
' Create the binding.
Dim myBinding As New WSHttpBinding()
myBinding.Security.Mode = SecurityMode.Message
myBinding.Security.Message.ClientCredentialType = _
   MessageCredentialType.Windows

' Disable credential negotiation and the establishment of
' a security context.
myBinding.Security.Message.NegotiateServiceCredential = False
myBinding.Security.Message.EstablishSecurityContext = False

' Create the endpoint address and set the SPN identity.
' The SPN must match the identity of the service's SPN.
' If using SvcUtil to generate a configuration file, the SPN
' will be published as the <servicePrincipalName> element under the
' <identity> element.
Dim ea As New EndpointAddress(New Uri("http://machineName/calculator"), _
EndpointIdentity.CreateSpnIdentity("service_spn_name"))

' Create the client.
Dim cc As New CalculatorClient(myBinding, ea)

' Begin using the client.
Try
    cc.Open()

    Console.WriteLine(cc.Add(100, 11))
    Console.ReadLine()

    ' Close the client.
    cc.Close()
Catch tex As TimeoutException
    Console.WriteLine(tex.Message)
    cc.Abort()
Catch cex As CommunicationException
    Console.WriteLine(cex.Message)
    cc.Abort()
Finally
    Console.WriteLine("Closed the client")
    Console.ReadLine()
End Try

Configuratie

Met de volgende code wordt de client geconfigureerd. Houd er rekening mee dat het <element servicePrincipalName> moet worden ingesteld op overeenstemming met de SPN van de service als geregistreerd voor het account van de service in het Active Directory-domein.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_ICalculator" >
          <security mode="Message">
            <message clientCredentialType="Windows"
                     negotiateServiceCredential="false"
                     establishSecurityContext="false" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/Calculator"
                binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_ICalculator"
                contract="ICalculator"
                name="WSHttpBinding_ICalculator">
        <identity>
          <servicePrincipalName value="service_spn_name" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

Zie ook