Token Authenticator
In dit voorbeeld ziet u hoe u een aangepaste token authenticator implementeert. Een token authenticator in Windows Communication Foundation (WCF) wordt gebruikt voor het valideren van het token dat met het bericht wordt gebruikt, waarbij wordt gecontroleerd of het zelfconsistent is en de identiteit verifieert die aan het token is gekoppeld.
Aangepaste token authenticators zijn handig in verschillende gevallen, zoals:
Wanneer u het standaardverificatiemechanisme wilt overschrijven dat is gekoppeld aan een token.
Wanneer u een aangepast token bouwt.
In dit voorbeeld ziet u het volgende:
Hoe een client kan verifiëren met behulp van een gebruikersnaam/wachtwoordpaar.
Hoe de server de clientreferenties kan valideren met behulp van een aangepaste token authenticator.
Hoe de WCF-servicecode is gekoppeld aan de aangepaste token authenticator.
Hoe de server kan worden geverifieerd met behulp van het X.509-certificaat van de server.
In dit voorbeeld ziet u ook hoe de identiteit van de beller toegankelijk is vanuit WCF na het aangepaste tokenverificatieproces.
De service maakt één eindpunt beschikbaar voor communicatie met de service, gedefinieerd met behulp van het configuratiebestand App.config. Het eindpunt bestaat uit een adres, een binding en een contract. De binding is geconfigureerd met een standaard wsHttpBinding
, waarbij de beveiligingsmodus is ingesteld op bericht - de standaardmodus van de wsHttpBinding
. In dit voorbeeld wordt de standaard wsHttpBinding
ingesteld voor het gebruik van verificatie van clientgebruikersnamen. De service configureert ook het servicecertificaat met behulp van serviceCredentials
gedrag. Met het securityCredentials
gedrag kunt u een servicecertificaat opgeven. Een servicecertificaat wordt door een client gebruikt om de service te verifiëren en berichtbeveiliging te bieden. De volgende configuratie verwijst naar het localhost-certificaat dat is geïnstalleerd tijdens de voorbeeldinstallatie, zoals beschreven in de volgende installatie-instructies.
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<!-- configure base address provided by host -->
<add baseAddress ="http://localhost:8000/servicemodelsamples/service" />
</baseAddresses>
</host>
<!-- use base address provided by host -->
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by a client to authenticate the service and provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
.... -->
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
De configuratie van het clienteindpunt bestaat uit een configuratienaam, een absoluut adres voor het service-eindpunt, de binding en het contract. De clientbinding is geconfigureerd met de juiste Mode
en clientCredentialType
.
<system.serviceModel>
<client>
<endpoint name=""
address="http://localhost:8000/servicemodelsamples/service"
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
De client-implementatie stelt de gebruikersnaam en het wachtwoord in die moeten worden gebruikt.
static void Main()
{
...
client.ClientCredentials.UserNamePassword.UserName = username;
client.ClientCredentials.UserNamePassword.Password = password;
...
}
Aangepaste token authenticator
Gebruik de volgende stappen om een aangepaste token authenticator te maken:
Schrijf een aangepaste token authenticator.
In het voorbeeld wordt een aangepaste token authenticator geïmplementeerd waarmee wordt gevalideerd of de gebruikersnaam een geldige e-mailindeling heeft. Het leidt de UserNameSecurityTokenAuthenticator. De belangrijkste methode in deze klasse is ValidateUserNamePasswordCore(String, String). In deze methode valideert de verificator de indeling van de gebruikersnaam en ook dat de hostnaam niet afkomstig is van een rogue domein. Als aan beide voorwaarden wordt voldaan, retourneert deze een alleen-lezen verzameling IAuthorizationPolicy exemplaren die vervolgens worden gebruikt om claims op te geven die de gegevens vertegenwoordigen die zijn opgeslagen in het gebruikersnaamtoken.
protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateUserNamePasswordCore(string userName, string password) { if (!ValidateUserNameFormat(userName)) throw new SecurityTokenValidationException("Incorrect UserName format"); ClaimSet claimSet = new DefaultClaimSet(ClaimSet.System, new Claim(ClaimTypes.Name, userName, Rights.PossessProperty)); List<IIdentity> identities = new List<IIdentity>(1); identities.Add(new GenericIdentity(userName)); List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1); policies.Add(new UnconditionalPolicy(ClaimSet.System, claimSet, DateTime.MaxValue.ToUniversalTime(), identities)); return policies.AsReadOnly(); }
Geef een autorisatiebeleid op dat wordt geretourneerd door een aangepaste token-verificator.
Dit voorbeeld biedt een eigen implementatie van IAuthorizationPolicy aangeroepen
UnconditionalPolicy
die een set claims en identiteiten retourneert die zijn doorgegeven in de constructor.class UnconditionalPolicy : IAuthorizationPolicy { String id = Guid.NewGuid().ToString(); ClaimSet issuer; ClaimSet issuance; DateTime expirationTime; IList<IIdentity> identities; public UnconditionalPolicy(ClaimSet issuer, ClaimSet issuance, DateTime expirationTime, IList<IIdentity> identities) { if (issuer == null) throw new ArgumentNullException("issuer"); if (issuance == null) throw new ArgumentNullException("issuance"); this.issuer = issuer; this.issuance = issuance; this.identities = identities; this.expirationTime = expirationTime; } public string Id { get { return this.id; } } public ClaimSet Issuer { get { return this.issuer; } } public DateTime ExpirationTime { get { return this.expirationTime; } } public bool Evaluate(EvaluationContext evaluationContext, ref object state) { evaluationContext.AddToTarget(this, this.issuance); if (this.identities != null) { object value; IList<IIdentity> contextIdentities; if (!evaluationContext.Properties.TryGetValue("Identities", out value)) { contextIdentities = new List<IIdentity>(this.identities.Count); evaluationContext.Properties.Add("Identities", contextIdentities); } else { contextIdentities = value as IList<IIdentity>; } foreach (IIdentity identity in this.identities) { contextIdentities.Add(identity); } } evaluationContext.RecordExpirationTime(this.expirationTime); return true; } }
Een aangepast beveiligingstokenbeheer schrijven.
De SecurityTokenManager methode wordt gebruikt om een SecurityTokenAuthenticator voor specifieke SecurityTokenRequirement objecten te maken die eraan worden doorgegeven in de
CreateSecurityTokenAuthenticator
methode. Het beveiligingstokenbeheer wordt ook gebruikt om tokenproviders en tokenserialisaties te maken, maar die vallen niet onder dit voorbeeld. In dit voorbeeld neemt de aangepaste beveiligingstokenbeheerder de klasse over ServiceCredentialsSecurityTokenManager en overschrijft deCreateSecurityTokenAuthenticator
methode om aangepaste verificatie van gebruikersnaamtoken te retourneren wanneer de doorgegeven tokenvereisten aangeven dat verificator voor gebruikersnaam wordt aangevraagd.public class MySecurityTokenManager : ServiceCredentialsSecurityTokenManager { MyUserNameCredential myUserNameCredential; public MySecurityTokenManager(MyUserNameCredential myUserNameCredential) : base(myUserNameCredential) { this.myUserNameCredential = myUserNameCredential; } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { if (tokenRequirement.TokenType == SecurityTokenTypes.UserName) { outOfBandTokenResolver = null; return new MyTokenAuthenticator(); } else { return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } } }
Een aangepaste servicereferentie schrijven.
De klasse servicereferenties wordt gebruikt om de referenties te vertegenwoordigen die zijn geconfigureerd voor de service en maakt een beveiligingstokenbeheerder die wordt gebruikt voor het verkrijgen van token authenticators, tokenproviders en tokenserialisaties.
public class MyUserNameCredential : ServiceCredentials { public MyUserNameCredential() : base() { } protected override ServiceCredentials CloneCore() { return new MyUserNameCredential(); } public override SecurityTokenManager CreateSecurityTokenManager() { return new MySecurityTokenManager(this); } }
Configureer de service voor het gebruik van de aangepaste servicereferenties.
Om ervoor te zorgen dat de service de aangepaste servicereferenties gebruikt, verwijderen we de standaardservicereferentieklasse na het vastleggen van het servicecertificaat dat al vooraf is geconfigureerd in de standaardservicereferentie en configureren we het nieuwe servicereferentieexemplaren om de vooraf geconfigureerde servicecertificaten te gebruiken en dit nieuwe servicereferentie-exemplaar toe te voegen aan servicegedrag.
ServiceCredentials sc = serviceHost.Credentials; X509Certificate2 cert = sc.ServiceCertificate.Certificate; MyUserNameCredential serviceCredential = new MyUserNameCredential(); serviceCredential.ServiceCertificate.Certificate = cert; serviceHost.Description.Behaviors.Remove((typeof(ServiceCredentials))); serviceHost.Description.Behaviors.Add(serviceCredential);
Als u de gegevens van de beller wilt weergeven, kunt u de PrimaryIdentity informatie gebruiken zoals wordt weergegeven in de volgende code. De Current bevat informatie over claims over de huidige beller.
static void DisplayIdentityInformation()
{
Console.WriteLine("\t\tSecurity context identity : {0}",
ServiceSecurityContext.Current.PrimaryIdentity.Name);
return;
}
Wanneer u het voorbeeld uitvoert, worden de bewerkingsaanvragen en -antwoorden weergegeven in het clientconsolevenster. Druk op Enter in het clientvenster om de client af te sluiten.
Batch-bestand instellen
Met het Setup.bat batchbestand dat in dit voorbeeld is opgenomen, kunt u de server configureren met relevante certificaten om een zelf-hostende toepassing uit te voeren waarvoor beveiliging op basis van servercertificaten is vereist. Dit batchbestand moet worden gewijzigd om te kunnen werken op computers of om te kunnen werken in een niet-gehost geval.
Hieronder vindt u een kort overzicht van de verschillende secties van de batchbestanden, zodat ze kunnen worden gewijzigd om in de juiste configuratie te worden uitgevoerd.
Het servercertificaat maken.
De volgende regels uit het Setup.bat batchbestand maken het servercertificaat dat moet worden gebruikt. De
%SERVER_NAME%
variabele geeft de servernaam op. Wijzig deze variabele om uw eigen servernaam op te geven. De standaardinstelling in dit batchbestand is localhost.echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
Het servercertificaat installeren in het vertrouwde certificaatarchief van de client.
Met de volgende regels in het Setup.bat batchbestand kopieert u het servercertificaat naar het archief vertrouwde personen van de client. Deze stap is vereist omdat certificaten die worden gegenereerd door Makecert.exe niet impliciet worden vertrouwd door het clientsysteem. Als u al een certificaat hebt dat is geroot in een vertrouwd basiscertificaat van een client, bijvoorbeeld een door Microsoft uitgegeven certificaat, is deze stap van het vullen van het clientcertificaatarchief met het servercertificaat niet vereist.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Notitie
Het installatiebatchbestand is ontworpen om te worden uitgevoerd vanaf een Windows SDK-opdrachtprompt. Hiervoor moet de omgevingsvariabele MSSDK verwijzen naar de map waarin de SDK is geïnstalleerd. Deze omgevingsvariabele wordt automatisch ingesteld in een Windows SDK-opdrachtprompt.
Het voorbeeld instellen en bouwen
Zorg ervoor dat u de eenmalige installatieprocedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.
Volg de instructies in Het bouwen van de Windows Communication Foundation-voorbeelden om de oplossing te bouwen.
Het voorbeeld uitvoeren op dezelfde computer
Voer Setup.bat uit vanuit de voorbeeldinstallatiemap in een Visual Studio-opdrachtprompt die is geopend met beheerdersbevoegdheden. Hiermee worden alle certificaten geïnstalleerd die vereist zijn voor het uitvoeren van het voorbeeld.
Notitie
Het Setup.bat batchbestand is ontworpen om te worden uitgevoerd vanaf een Visual Studio-opdrachtprompt. De omgevingsvariabele PATH die in de Visual Studio-opdrachtprompt is ingesteld, verwijst naar de map met uitvoerbare bestanden die zijn vereist voor het Setup.bat script.
Start service.exe vanuit service\bin.
Start client.exe vanuit \client\bin. Clientactiviteit wordt weergegeven in de clientconsoletoepassing.
Als de client en service niet kunnen communiceren, raadpleegt u Tips voor probleemoplossing voor WCF-voorbeelden.
Het voorbeeld uitvoeren op computers
Maak een map op de servicecomputer voor de binaire servicebestanden.
Kopieer de serviceprogrammabestanden naar de servicemap op de servicecomputer. Kopieer ook de Setup.bat- en Cleanup.bat-bestanden naar de servicecomputer.
U moet een servercertificaat hebben met de onderwerpnaam die de volledig gekwalificeerde domeinnaam van de computer bevat. Het service-app.config-bestand moet worden bijgewerkt om deze nieuwe certificaatnaam weer te geven. U kunt er een maken met behulp van de Setup.bat als u de
%SERVER_NAME%
variabele instelt op volledig gekwalificeerde hostnaam van de computer waarop de service wordt uitgevoerd. Houd er rekening mee dat het setup.bat-bestand moet worden uitgevoerd vanaf een opdrachtprompt voor ontwikkelaars voor Visual Studio die is geopend met beheerdersbevoegdheden.Kopieer het servercertificaat naar het archief CurrentUser-Trusted Mensen van de client. U hoeft dit niet te doen, behalve wanneer het servercertificaat wordt uitgegeven door een vertrouwde verlener van een client.
Wijzig in het bestand App.config op de servicecomputer de waarde van het basisadres om een volledig gekwalificeerde computernaam op te geven in plaats van localhost.
Voer op de servicecomputer service.exe uit vanaf een opdrachtprompt.
Kopieer de clientprogrammabestanden uit de map \client\bin\ onder de taalspecifieke map naar de clientcomputer.
Wijzig in het bestand Client.exe.config op de clientcomputer de adreswaarde van het eindpunt zodat deze overeenkomt met het nieuwe adres van uw service.
Start Client.exe vanaf een opdrachtprompt op de clientcomputer.
Als de client en service niet kunnen communiceren, raadpleegt u Tips voor probleemoplossing voor WCF-voorbeelden.
Opschonen na het voorbeeld
- Voer Cleanup.bat uit in de map met voorbeelden zodra u klaar bent met het uitvoeren van het voorbeeld.