Procedura: creare un gestore autorizzazioni personalizzato per un servizio
L'infrastruttura dei modelli di identità di Windows Communication Foundation (WCF) supporta un modello di autorizzazione basato su attestazioni estensibili. Le attestazioni vengono estratte dai token, elaborate facoltativamente da criteri di autorizzazione personalizzati e quindi inserite in una classe AuthorizationContext. Un gestore autorizzazioni esamina le attestazioni contenute nel contesto AuthorizationContext per prendere decisioni di autorizzazione.
Per impostazione predefinita, le decisioni di autorizzazione sono prese dalla classe ServiceAuthorizationManager. È tuttavia possibile creare un gestore autorizzazioni personalizzato per eseguire l'override di queste decisioni. Per creare un gestore autorizzazioni personalizzato, creare una classe che deriva da ServiceAuthorizationManager e che implementa il metodo CheckAccessCore. Le decisioni di autorizzazione sono prese tramite il metodo CheckAccessCore che restituisce true quando l'accesso è concesso e false quando l'accesso è negato.
Se la decisione di autorizzazione dipende dal contenuto del corpo del messaggio, utilizzare il metodo CheckAccess.
A causa di problemi riguardanti le prestazioni, è consigliabile ridisegnare l'applicazione, se possibile, in modo tale che per la decisione di autorizzazione non sia necessario l'accesso al corpo del messaggio.
La registrazione del gestore autorizzazioni personalizzato per un servizio può essere eseguita in codice o in configurazione.
Per creare un gestore autorizzazioni personalizzato
Derivare una classe dalla classe ServiceAuthorizationManager.
Public Class MyServiceAuthorizationManager Inherits ServiceAuthorizationManager
public class MyServiceAuthorizationManager : ServiceAuthorizationManager {
Eseguire l'override del metodo CheckAccessCore.
Utilizzare il contesto OperationContext passato al metodo CheckAccessCore per prendere decisioni di autorizzazione.
Nell'esempio di codice seguente il metodo FindClaims viene utilizzato per individuare l'attestazione personalizzata
https://www.contoso.com/claims/allowedoperation
allo scopo di prendere una decisione di autorizzazione.Protected Overrides Function CheckAccessCore(ByVal operationContext As OperationContext) As Boolean ' Extract the action URI from the OperationContext. Match this against the claims. ' in the AuthorizationContext. Dim action As String = operationContext.RequestContext.RequestMessage.Headers.Action ' Iterate through the various claimsets in the AuthorizationContext. Dim cs As ClaimSet For Each cs In operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets ' Examine only those claim sets issued by System. If cs.Issuer Is ClaimSet.System Then ' Iterate through claims of type "https://www.contoso.com/claims/allowedoperation". Dim c As Claim For Each c In cs.FindClaims("https://www.contoso.com/claims/allowedoperation", _ Rights.PossessProperty) ' If the Claim resource matches the action URI then return true to allow access. If action = c.Resource.ToString() Then Return True End If Next c End If Next cs ' If this point is reached, return false to deny access. Return False End Function
protected override bool CheckAccessCore(OperationContext operationContext) { // Extract the action URI from the OperationContext. Match this against the claims // in the AuthorizationContext. string action = operationContext.RequestContext.RequestMessage.Headers.Action; // Iterate through the various claim sets in the AuthorizationContext. foreach(ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets) { // Examine only those claim sets issued by System. if (cs.Issuer == ClaimSet.System) { // Iterate through claims of type "https://www.contoso.com/claims/allowedoperation". foreach (Claim c in cs.FindClaims("https://www.contoso.com/claims/allowedoperation", Rights.PossessProperty)) { // If the Claim resource matches the action URI then return true to allow access. if (action == c.Resource.ToString()) return true; } } } // If this point is reached, return false to deny access. return false; }
Per registrare un gestore autorizzazioni personalizzato in codice
Creare un'istanza del gestore autorizzazioni personalizzato e assegnarla alla proprietà ServiceAuthorizationManager.
Per accedere al comportamento ServiceAuthorizationBehavior è possibile utilizzare la proprietà Authorization.
Nell'esempio di codice seguente viene illustrato come registrare il gestore autorizzazioni personalizzato
MyServiceAuthorizationManager
.' Add a custom authorization manager to the service authorization behavior. serviceHost.Authorization.ServiceAuthorizationManager = _ New MyServiceAuthorizationManager()
// Add a custom authorization manager to the service authorization behavior. serviceHost.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();
Per registrare un gestore autorizzazioni personalizzato in configurazione
Aprire il file di configurazione del servizio.
Aggiungere un serviceAuthorization element all'Behaviors element.
Aggiungere un attributo serviceAuthorizationManagerType all'serviceAuthorization element e quindi impostare il valore di tale attributo sul tipo che rappresenta il gestore autorizzazioni personalizzato.
Aggiungere un'associazione in grado di proteggere la comunicazione tra client e servizio.
L'associazione scelta per questa comunicazione determina le attestazioni aggiunte al contesto AuthorizationContext utilizzate dal gestore autorizzazioni personalizzato per prendere le decisioni di autorizzazione. Per ulteriori dettagli sulle associazioni fornite dal sistema, vedere Associazioni fornite dal sistema.
Associare il comportamento a un endpoint di servizio aggiungendo un elemento <service>behaviorConfiguration e quindi impostare il valore dell'attributo <behavior> of <serviceBehaviors> sul valore dell'attributo nome dell'elemento.
Per ulteriori informazioni sulla configurazione di un endpoint di servizio, vedere Procedura: creare un endpoint di servizio nella configurazione.
Nell'esempio di codice seguente viene illustrato come registrare il gestore autorizzazioni personalizzato
Samples.MyServiceAuthorizationManager
.<configuration> <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior"> <host> <baseAddresses> <add baseAddress="https://localhost:8000/ServiceModelSamples/service"/> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding_Calculator" contract="Microsoft.ServiceModel.Samples.ICalculator" /> </service> </services> <bindings> <WSHttpBinding> <binding name = "wsHttpBinding_Calculator"> <security mode="Message"> <message clientCredentialType="Windows"/> </security> </binding> </WSHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="CalculatorServiceBehavior"> <serviceAuthorization serviceAuthorizationManagerType="Samples.MyServiceAuthorizationManager" /> </behaviors> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
Esempio
Nell'esempio di codice seguente viene descritta un'implementazione di base di una classe ServiceAuthorizationManager che prevede l'override del metodo CheckAccessCore. Nell'esempio di codice viene eseguita una ricerca all'interno del contesto AuthorizationContext allo scopo di individuare un'attestazione personalizzata e quindi viene restituito true quando la risorsa relativa a tale attestazione personalizzata corrisponde al valore di azione indicato nel contesto OperationContext. Per un'implementazione più completa di una classe ServiceAuthorizationManager, vedere Criteri di autorizzazione.
Public Class MyServiceAuthorizationManager
Inherits ServiceAuthorizationManager
Protected Overrides Function CheckAccessCore(ByVal operationContext As OperationContext) As Boolean
' Extract the action URI from the OperationContext. Match this against the claims.
' in the AuthorizationContext.
Dim action As String = operationContext.RequestContext.RequestMessage.Headers.Action
' Iterate through the various claimsets in the AuthorizationContext.
Dim cs As ClaimSet
For Each cs In operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets
' Examine only those claim sets issued by System.
If cs.Issuer Is ClaimSet.System Then
' Iterate through claims of type "https://www.contoso.com/claims/allowedoperation".
Dim c As Claim
For Each c In cs.FindClaims("https://www.contoso.com/claims/allowedoperation", _
Rights.PossessProperty)
' If the Claim resource matches the action URI then return true to allow access.
If action = c.Resource.ToString() Then
Return True
End If
Next c
End If
Next cs
' If this point is reached, return false to deny access.
Return False
End Function
End Class
public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
// Extract the action URI from the OperationContext. Match this against the claims
// in the AuthorizationContext.
string action = operationContext.RequestContext.RequestMessage.Headers.Action;
// Iterate through the various claim sets in the AuthorizationContext.
foreach(ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
{
// Examine only those claim sets issued by System.
if (cs.Issuer == ClaimSet.System)
{
// Iterate through claims of type "https://www.contoso.com/claims/allowedoperation".
foreach (Claim c in cs.FindClaims("https://www.contoso.com/claims/allowedoperation", Rights.PossessProperty))
{
// If the Claim resource matches the action URI then return true to allow access.
if (action == c.Resource.ToString())
return true;
}
}
}
// If this point is reached, return false to deny access.
return false;
}
}
Vedere anche
Attività
Criteri di autorizzazione
Criteri di autorizzazione