Procedure: Een aangepaste clientidentiteitsverificator maken
Met de identiteitsfunctie van Windows Communication Foundation (WCF) kan een client vooraf de verwachte identiteit van de service opgeven. Wanneer een server zichzelf verifieert bij de client, wordt de identiteit gecontroleerd op basis van de verwachte identiteit. (Zie voor een uitleg van identiteit en hoe het werkt Service-identiteit en -verificatie.)
Indien nodig kan de verificatie worden aangepast met behulp van een aangepaste identiteitsverificator. U kunt bijvoorbeeld aanvullende verificatiecontroles voor service-identiteiten uitvoeren. In dit voorbeeld controleert de aangepaste identiteitscontrole aanvullende claims in het X.509-certificaat dat is geretourneerd door de server. Zie Service Identity Sample voor een voorbeeldtoepassing.
De EndpointIdentity-klasse uitbreiden
Definieer een nieuwe klasse die is afgeleid van de EndpointIdentity klasse. In dit voorbeeld wordt de extensie
OrgEndpointIdentity
genoemd.Voeg privéleden toe, samen met eigenschappen die door de uitgebreide IdentityVerifier klasse worden gebruikt om de identiteitscontrole uit te voeren op claims in het beveiligingstoken dat wordt geretourneerd door de service. In dit voorbeeld wordt één eigenschap gedefinieerd: de
OrganizationClaim
eigenschap.public class OrgEndpointIdentity : EndpointIdentity { private string orgClaim; public OrgEndpointIdentity(string orgName) { orgClaim = orgName; } public string OrganizationClaim { get { return orgClaim; } set { orgClaim = value; } } }
Public Class OrgEndpointIdentity Inherits EndpointIdentity Private orgClaim As String Public Sub New(ByVal orgName As String) orgClaim = orgName End Sub Public Property OrganizationClaim() As String Get Return orgClaim End Get Set(ByVal value As String) orgClaim = value End Set End Property End Class
De IdentityVerifier-klasse uitbreiden
Definieer een nieuwe klasse die is afgeleid van IdentityVerifier. In dit voorbeeld wordt de extensie
CustomIdentityVerifier
genoemd.public class CustomIdentityVerifier : IdentityVerifier { // Code to be added. public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext) { throw new Exception("The method or operation is not implemented."); } public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity) { throw new Exception("The method or operation is not implemented."); } }
Public Class CustomIdentityVerifier Inherits IdentityVerifier ' Code to be added. Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _ ByVal authContext As AuthorizationContext) As Boolean Throw New Exception("The method or operation is not implemented.") End Function Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _ <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean Throw New Exception("The method or operation is not implemented.") End Function End Class
Overschrijf de CheckAccess methode. De methode bepaalt of de identiteitscontrole is geslaagd of mislukt.
De
CheckAccess
methode heeft twee parameters. De eerste is een instantie van de EndpointIdentity klasse. De tweede is een instantie van de AuthorizationContext klasse.Bekijk in de methode-implementatie de verzameling claims die worden geretourneerd door de ClaimSets eigenschap van de AuthorizationContext klasse en voer waar nodig verificatiecontroles uit. Dit voorbeeld begint met het vinden van een claim van het type 'DN-naam' en vergelijkt vervolgens de naam met de extensie van de EndpointIdentity (
OrgEndpointIdentity
).public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext) { bool returnvalue = false; foreach (ClaimSet claimset in authContext.ClaimSets) { foreach (Claim claim in claimset) { if (claim.ClaimType == "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname") { X500DistinguishedName name = (X500DistinguishedName)claim.Resource; if (name.Name.Contains(((OrgEndpointIdentity)identity).OrganizationClaim)) { Console.WriteLine("Claim Type: {0}", claim.ClaimType); Console.WriteLine("Right: {0}", claim.Right); Console.WriteLine("Resource: {0}", claim.Resource); Console.WriteLine(); returnvalue = true; } } } } return returnvalue; }
Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _ ByVal authContext As AuthorizationContext) As Boolean Dim returnvalue = False For Each claimset In authContext.ClaimSets For Each claim In claimset If claim.ClaimType = "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname" Then Dim name = CType(claim.Resource, X500DistinguishedName) If name.Name.Contains((CType(identity, OrgEndpointIdentity)).OrganizationClaim) Then Console.WriteLine("Claim Type: {0}", claim.ClaimType) Console.WriteLine("Right: {0}", claim.Right) Console.WriteLine("Resource: {0}", claim.Resource) Console.WriteLine() returnvalue = True End If End If Next claim Next claimset Return returnvalue End Function
De TryGetIdentity-methode implementeren
Implementeer de TryGetIdentity methode, die bepaalt of een exemplaar van de EndpointIdentity klasse kan worden geretourneerd door de client. De WCF-infrastructuur roept eerst de implementatie van de
TryGetIdentity
methode aan om de identiteit van de service op te halen uit het bericht. Vervolgens roept de infrastructuur deCheckAccess
implementatie aan met de geretourneerdeEndpointIdentity
en AuthorizationContext.Plaats de volgende code in de
TryGetIdentity
methode:public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity) { return IdentityVerifier.CreateDefault().TryGetIdentity(reference, out identity); }
Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _ <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean Return IdentityVerifier.CreateDefault().TryGetIdentity(reference, identity) End Function
Een aangepaste binding implementeren en de aangepaste IdentityVerifier instellen
Maak een methode die een Binding object retourneert. In dit voorbeeld wordt een exemplaar van de WSHttpBinding klasse gemaakt en wordt de beveiligingsmodus ingesteld Messageop , en op ClientCredentialTypeNone.
Maak een BindingElementCollection met behulp van de CreateBindingElements methode.
Retourneer de SecurityBindingElement verzameling en cast deze naar een SymmetricSecurityBindingElement variabele.
Stel de IdentityVerifier eigenschap van de LocalClientSecuritySettings klasse in op een nieuw exemplaar van de
CustomIdentityVerifier
klasse die u eerder hebt gemaakt.public static Binding CreateCustomSecurityBinding() { WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message); //Clients are anonymous to the service. binding.Security.Message.ClientCredentialType = MessageCredentialType.None; //Secure conversation is turned off for simplification. If secure conversation is turned on, then //you also need to set the IdentityVerifier on the secureconversation bootstrap binding. binding.Security.Message.EstablishSecurityContext = false; // Get the SecurityBindingElement and cast to a SymmetricSecurityBindingElement to set the IdentityVerifier. BindingElementCollection outputBec = binding.CreateBindingElements(); SymmetricSecurityBindingElement ssbe = (SymmetricSecurityBindingElement)outputBec.Find<SecurityBindingElement>(); //Set the Custom IdentityVerifier. ssbe.LocalClientSettings.IdentityVerifier = new CustomIdentityVerifier(); return new CustomBinding(outputBec); }
Public Shared Function CreateCustomSecurityBinding() As Binding Dim binding As New WSHttpBinding(SecurityMode.Message) With binding.Security.Message 'Clients are anonymous to the service. .ClientCredentialType = MessageCredentialType.None 'Secure conversation is turned off for simplification. If secure conversation is turned on, then 'you also need to set the IdentityVerifier on the secureconversation bootstrap binding. .EstablishSecurityContext = False End With ' Get the SecurityBindingElement and cast to a SymmetricSecurityBindingElement to set the IdentityVerifier. Dim outputBec = binding.CreateBindingElements() Dim ssbe = CType(outputBec.Find(Of SecurityBindingElement)(), SymmetricSecurityBindingElement) 'Set the Custom IdentityVerifier. ssbe.LocalClientSettings.IdentityVerifier = New CustomIdentityVerifier() Return New CustomBinding(outputBec) End Function
De aangepaste binding die wordt geretourneerd, wordt gebruikt om een exemplaar van de client en klasse te maken. De client kan vervolgens een aangepaste identiteitsverificatie van de service uitvoeren, zoals wordt weergegeven in de volgende code.
using (CalculatorClient client = new CalculatorClient(customSecurityBinding, serviceAddress)) {
Using client As New CalculatorClient(customSecurityBinding, serviceAddress)
Voorbeeld 1
In het volgende voorbeeld ziet u een volledige implementatie van de IdentityVerifier klasse.
class CustomIdentityVerifier : IdentityVerifier
{
public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
{
bool returnvalue = false;
foreach (ClaimSet claimset in authContext.ClaimSets)
{
foreach (Claim claim in claimset)
{
if (claim.ClaimType == "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname")
{
X500DistinguishedName name = (X500DistinguishedName)claim.Resource;
if (name.Name.Contains(((OrgEndpointIdentity)identity).OrganizationClaim))
{
Console.WriteLine("Claim Type: {0}", claim.ClaimType);
Console.WriteLine("Right: {0}", claim.Right);
Console.WriteLine("Resource: {0}", claim.Resource);
Console.WriteLine();
returnvalue = true;
}
}
}
}
return returnvalue;
}
public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity)
{
return IdentityVerifier.CreateDefault().TryGetIdentity(reference, out identity);
}
}
Friend Class CustomIdentityVerifier
Inherits IdentityVerifier
Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _
ByVal authContext As AuthorizationContext) As Boolean
Dim returnvalue = False
For Each claimset In authContext.ClaimSets
For Each claim In claimset
If claim.ClaimType = "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname" Then
Dim name = CType(claim.Resource, X500DistinguishedName)
If name.Name.Contains((CType(identity, OrgEndpointIdentity)).OrganizationClaim) Then
Console.WriteLine("Claim Type: {0}", claim.ClaimType)
Console.WriteLine("Right: {0}", claim.Right)
Console.WriteLine("Resource: {0}", claim.Resource)
Console.WriteLine()
returnvalue = True
End If
End If
Next claim
Next claimset
Return returnvalue
End Function
Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _
<System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean
Return IdentityVerifier.CreateDefault().TryGetIdentity(reference, identity)
End Function
End Class
Voorbeeld 2
In het volgende voorbeeld ziet u een volledige implementatie van de EndpointIdentity klasse.
public class OrgEndpointIdentity : EndpointIdentity
{
private string orgClaim;
public OrgEndpointIdentity(string orgName)
{
orgClaim = orgName;
}
public string OrganizationClaim
{
get { return orgClaim; }
set { orgClaim = value; }
}
}
Public Class OrgEndpointIdentity
Inherits EndpointIdentity
Private orgClaim As String
Public Sub New(ByVal orgName As String)
orgClaim = orgName
End Sub
Public Property OrganizationClaim() As String
Get
Return orgClaim
End Get
Set(ByVal value As String)
orgClaim = value
End Set
End Property
End Class