Vertrouwde gevelservice
Het voorbeeld TrustedFacade laat zien hoe de identiteitsgegevens van de ene service naar de andere worden gestroomd met behulp van de WCF-beveiligingsinfrastructuur (Windows Communication Foundation).
Het is een algemeen ontwerppatroon om de functionaliteit van een service beschikbaar te maken voor het openbare netwerk met behulp van een façadeservice. De gevelservice bevindt zich doorgaans in het perimeternetwerk (ook wel DMZ, gedemilitariseerde zone en gescreend subnet genoemd) en communiceert met een back-endservice waarmee de bedrijfslogica wordt geïmplementeerd en toegang heeft tot interne gegevens. Het communicatiekanaal tussen de gevelservice en de back-endservice gaat via een firewall en is meestal beperkt voor één doel.
Dit voorbeeld bestaat uit de volgende onderdelen:
Rekenmachineclient
Rekenmachine façade service
Back-endservice van rekenmachine
De gevelservice is verantwoordelijk voor het valideren van de aanvraag en het verifiëren van de beller. Na een geslaagde verificatie en validatie wordt de aanvraag doorgestuurd naar de back-endservice met behulp van het beheerde communicatiekanaal van het perimeternetwerk naar het interne netwerk. Als onderdeel van de doorgestuurde aanvraag bevat de façadeservice informatie over de identiteit van de beller, zodat de back-endservice deze informatie in de verwerking kan gebruiken. De identiteit van de beller wordt verzonden met behulp van een Username
beveiligingstoken in de berichtkop Security
. In het voorbeeld wordt de WCF-beveiligingsinfrastructuur gebruikt om deze informatie uit de Security
header te verzenden en te extraheren.
Belangrijk
De back-endservice vertrouwt de façadeservice om de beller te verifiëren. Daarom verifieert de back-endservice de aanroeper niet opnieuw; deze maakt gebruik van de identiteitsgegevens die door de façadeservice in de doorgestuurde aanvraag worden verstrekt. Vanwege deze vertrouwensrelatie moet de back-endservice de façadeservice verifiëren om ervoor te zorgen dat het doorgestuurde bericht afkomstig is van een vertrouwde bron, in dit geval de gevelservice.
Implementatie
In dit voorbeeld zijn er twee communicatiepaden. De eerste is tussen de client en de gevelservice, de tweede is tussen de gevelservice en de back-endservice.
Communicatiepad tussen Client en Façade Service
De client naar het communicatiepad voor de façadeservice gebruikt wsHttpBinding
met een UserName
clientreferentietype. Dit betekent dat de client gebruikmaakt van een gebruikersnaam en wachtwoord voor verificatie bij de façadeservice en de façadeservice X.509-certificaat gebruikt om te verifiëren bij de client. De bindingsconfiguratie ziet eruit als in het volgende voorbeeld.
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
De façadeservice verifieert de aanroeper met behulp van aangepaste UserNamePasswordValidator
implementatie. Voor demonstratiedoeleinden zorgt de verificatie alleen ervoor dat de gebruikersnaam van de beller overeenkomt met het weergegeven wachtwoord. In de praktijk wordt de gebruiker waarschijnlijk geverifieerd met behulp van Active Directory of aangepaste ASP.NET lidmaatschapsprovider. De validatie-implementatie bevindt zich in FacadeService.cs
het bestand.
public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
// check that username matches password
if (null == userName || userName != password)
{
Console.WriteLine("Invalid username or password");
throw new SecurityTokenValidationException(
"Invalid username or password");
}
}
}
De aangepaste validator is geconfigureerd voor gebruik binnen het serviceCredentials
gedrag in het configuratiebestand van de façadeservice. Dit gedrag wordt ook gebruikt om het X.509-certificaat van de service te configureren.
<behaviors>
<serviceBehaviors>
<behavior name="FacadeServiceBehavior">
<!--The serviceCredentials behavior allows you to define -->
<!--a service certificate. -->
<!--A service certificate is used by the service to -->
<!--authenticate itself to its clients and to provide -->
<!--message protection. -->
<!--This configuration references the "localhost" -->
<!--certificate installed during the setup instructions. -->
<serviceCredentials>
<serviceCertificate
findValue="localhost"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType=
"Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator,
FacadeService"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Communicatiepad tussen façadeservice en back-endservice
De gevelservice naar het communicatiepad van de back-endservice maakt gebruik van verschillende customBinding
bindingselementen. Deze binding bereikt twee dingen. De façadeservice en back-endservice worden geverifieerd om ervoor te zorgen dat de communicatie veilig is en afkomstig is van een vertrouwde bron. Daarnaast verzendt het ook de identiteit van de initiële beller binnen het Username
beveiligingstoken. In dit geval wordt alleen de gebruikersnaam van de eerste beller verzonden naar de back-endservice. Het wachtwoord wordt niet opgenomen in het bericht. Dit komt doordat de back-endservice de façadeservice vertrouwt om de beller te verifiëren voordat de aanvraag naar de service wordt doorgestuurd. Omdat de façadeservice zichzelf verifieert bij de back-endservice, kan de back-endservice de informatie in de doorgestuurde aanvraag vertrouwen.
Hier volgt de bindingsconfiguratie voor dit communicatiepad.
<bindings>
<customBinding>
<binding name="ClientBinding">
<security authenticationMode="UserNameOverTransport"/>
<windowsStreamSecurity/>
<tcpTransport/>
</binding>
</customBinding>
</bindings>
Het <beveiligingsbindingselement> zorgt voor de initiële overdracht en extractie van de gebruikersnaam van de initiële beller. De <windowsStreamSecurity> en <tcpTransport> zorgen voor het verifiëren van gevel- en back-endservices en berichtbeveiliging.
Als u de aanvraag wilt doorsturen, moet de implementatie van de façadeservice de gebruikersnaam van de initiële beller opgeven, zodat de WCF-beveiligingsinfrastructuur dit in het doorgestuurde bericht kan plaatsen. De gebruikersnaam van de eerste beller wordt verstrekt in de implementatie van de façadeservice door deze in te stellen in de ClientCredentials
eigenschap op het clientproxy-exemplaar dat door de façadeservice wordt gebruikt om te communiceren met de back-endservice.
De volgende code laat zien hoe GetCallerIdentity
de methode wordt geïmplementeerd op de gevelservice. Andere methoden gebruiken hetzelfde patroon.
public string GetCallerIdentity()
{
CalculatorClient client = new CalculatorClient();
client.ClientCredentials.UserName.UserName = ServiceSecurityContext.Current.PrimaryIdentity.Name;
string result = client.GetCallerIdentity();
client.Close();
return result;
}
Zoals in de vorige code wordt weergegeven, is het wachtwoord niet ingesteld op de ClientCredentials
eigenschap, maar alleen de gebruikersnaam is ingesteld. In dit geval maakt de WCF-beveiligingsinfrastructuur een beveiligingstoken voor gebruikersnamen zonder een wachtwoord. Dit is precies wat in dit scenario vereist is.
In de back-endservice moeten de gegevens in het beveiligingstoken voor de gebruikersnaam worden geverifieerd. WcF-beveiliging probeert de gebruiker standaard toe te wijzen aan een Windows-account met behulp van het opgegeven wachtwoord. In dit geval is er geen wachtwoord opgegeven en is de back-endservice niet vereist om de gebruikersnaam te verifiëren omdat de verificatie al is uitgevoerd door de façadeservice. Als u deze functionaliteit in WCF wilt implementeren, wordt er een aangepaste UserNamePasswordValidator
functionaliteit geboden die alleen afdwingt dat een gebruikersnaam is opgegeven in het token en geen aanvullende verificatie uitvoert.
public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
// Ignore the password because it is empty,
// we trust the facade service to authenticate the client.
// Accept the username information here so that the
// application gets access to it.
if (null == userName)
{
Console.WriteLine("Invalid username");
throw new
SecurityTokenValidationException("Invalid username");
}
}
}
De aangepaste validator is geconfigureerd voor gebruik binnen het serviceCredentials
gedrag in het configuratiebestand van de façadeservice.
<behaviors>
<serviceBehaviors>
<behavior name="BackendServiceBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType=
"Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator,
BackendService"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
De implementatie van de back-endservice maakt gebruik van de ServiceSecurityContext
klasse om de gebruikersnaam en informatie over het vertrouwde façadeserviceaccount te extraheren. De volgende code laat zien hoe de GetCallerIdentity
methode wordt geïmplementeerd.
public string GetCallerIdentity()
{
// Facade service is authenticated using Windows authentication.
//Its identity is accessible.
// On ServiceSecurityContext.Current.WindowsIdentity.
string facadeServiceIdentityName =
ServiceSecurityContext.Current.WindowsIdentity.Name;
// The client name is transmitted using Username authentication on
//the message level without the password
// using a supporting encrypted UserNameToken.
// Claims extracted from this supporting token are available in
// ServiceSecurityContext.Current.AuthorizationContext.ClaimSets
// collection.
string clientName = null;
foreach (ClaimSet claimSet in
ServiceSecurityContext.Current.AuthorizationContext.ClaimSets)
{
foreach (Claim claim in claimSet)
{
if (claim.ClaimType == ClaimTypes.Name &&
claim.Right == Rights.Identity)
{
clientName = (string)claim.Resource;
break;
}
}
}
if (clientName == null)
{
// In case there was no UserNameToken attached to the request.
// In the real world implementation the service should reject
// this request.
return "Anonymous caller via " + facadeServiceIdentityName;
}
return clientName + " via " + facadeServiceIdentityName;
}
De informatie over het façadeserviceaccount wordt geëxtraheerd met behulp van de ServiceSecurityContext.Current.WindowsIdentity
eigenschap. Voor toegang tot de informatie over de eerste aanroeper gebruikt de back-endservice de ServiceSecurityContext.Current.AuthorizationContext.ClaimSets
eigenschap. Er wordt gezocht naar een Identity
claim met een type Name
. Deze claim wordt automatisch gegenereerd door de WCF-beveiligingsinfrastructuur op basis van de informatie in het Username
beveiligingstoken.
Het voorbeeld uitvoeren
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. U kunt op Enter drukken in de consolevensters voor de façade en back-endservice om de services af te sluiten.
Username authentication required.
Provide a valid machine or domain ac
Enter username:
user
Enter password:
****
user via MyMachine\testaccount
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Press <ENTER> to terminate client.
Met het Setup.bat batchbestand dat is opgenomen in het voorbeeld van het trusted facade-scenario, kunt u de server configureren met een relevant certificaat om de façadeservice uit te voeren waarvoor op certificaten gebaseerde beveiliging is vereist om zichzelf bij de client te verifiëren. Zie de installatieprocedure aan het einde van dit onderwerp voor meer informatie.
Hieronder vindt u een kort overzicht van de verschillende secties van de batchbestanden.
Het servercertificaat maken.
De volgende regels uit het Setup.bat batchbestand maken het servercertificaat dat moet worden gebruikt.
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
De
%SERVER_NAME%
variabele geeft de servernaam op: de standaardwaarde is localhost. Het certificaat wordt opgeslagen in het LocalMachine-archief.Het certificaat van de façadeservice installeren in het vertrouwde certificaatarchief van de client.
Met de volgende regel wordt het certificaat van de façadeservice gekopieerd 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 voor het invullen van het clientcertificaatarchief met het servercertificaat niet vereist.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Het voorbeeld instellen, compileren en uitvoeren
Zorg ervoor dat u de eenmalige installatieprocedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.
Als u de C# of Visual Basic .NET-editie van de oplossing wilt bouwen, volgt u de instructies in het bouwen van de Windows Communication Foundation-voorbeelden.
Het voorbeeld uitvoeren op dezelfde computer
Zorg ervoor dat het pad de map bevat waarin Makecert.exe zich bevindt.
Voer Setup.bat uit vanuit de voorbeeldinstallatiemap. Hiermee worden alle certificaten geïnstalleerd die vereist zijn voor het uitvoeren van het voorbeeld.
Start de BackendService.exe vanuit de map \BackendService\bin in een afzonderlijk consolevenster
Start de FacadeService.exe vanuit de map \FacadeService\bin in een afzonderlijk consolevenster
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.
Opschonen na het voorbeeld
- Voer Cleanup.bat uit in de map met voorbeelden zodra u klaar bent met het uitvoeren van het voorbeeld.