Procedimiento para crear un administrador de autorización personalizado para un servicio
En la infraestructura del modelo de identidad de Windows Communication Foundation (WCF), se admite el uso de un modelo de autorización extensible basado en demandas. Las demandas se extraen de los tokens y opcionalmente son procesadas por directivas de autorización personalizadas y, a continuación, colocadas en AuthorizationContext. Un administrador de autorización examina las demandas en AuthorizationContext para tomar las decisiones de autorización.
La clase ServiceAuthorizationManager toma de forma predeterminada, las decisiones de la autorización; sin embargo estas decisiones se pueden invalidar creando un administrador de autorización personalizado. Para crear un administrador de autorización personalizado, cree una clase que derive de ServiceAuthorizationManager e implemente el método CheckAccessCore. Las decisiones de la autorización se toman en el método CheckAccessCore, que devuelve true
cuando se permite el acceso y false
cuando se niega el acceso.
Si la decisión de autorización depende del contenido del cuerpo del mensaje, utilice el método CheckAccess.
Debido a los problemas de rendimiento, en la medida de lo posible debe rediseñar su aplicación para que la decisión de autorización no requiera el acceso al cuerpo del mensaje.
El registro del administrador de autorización personalizado para un servicio se puede hacer en código o configuración.
Para crear un administrador de autorización personalizado
Derive una clase de la clase ServiceAuthorizationManager.
public class MyServiceAuthorizationManager : ServiceAuthorizationManager {
Public Class MyServiceAuthorizationManager Inherits ServiceAuthorizationManager
Invalide el método CheckAccessCore(OperationContext) .
Utilice el OperationContext que se pasa al método CheckAccessCore(OperationContext) para tomar las decisiones de autorización.
El siguiente ejemplo de código utiliza el método FindClaims(String, String) para buscar el
http://www.contoso.com/claims/allowedoperation
de la notificación personalizada y tomar una decisión de autorización.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 "http://www.contoso.com/claims/allowedoperation". foreach (Claim c in cs.FindClaims("http://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; }
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 "http://www.contoso.com/claims/allowedoperation". Dim c As Claim For Each c In cs.FindClaims("http://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
Para registrar a un administrador de autorización personalizado mediante código
Cree una instancia del administrador de autorización personalizado y asígnelo a la propiedad ServiceAuthorizationManager.
Se puede tener acceso a ServiceAuthorizationBehavior mediante la propiedad Authorization.
El ejemplo de código siguiente registra el administrador de autorización personalizado
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()
Para registrar a un administrador de autorización personalizado mediante configuración
Abra el archivo de configuración para el servicio.
Agregue un elemento <serviceAuthorization> en la estructura <behaviors>.
En el elemento <serviceAuthorization>, agregue un atributo
serviceAuthorizationManagerType
y establezca su valor en el tipo que se use para representar al administrador de autorización personalizado.Agregue un enlace que proteja la comunicación entre el cliente y el servicio.
El enlace que se elige para esta comunicación determina las demandas que se agregan al AuthorizationContext, que el administrador de autorización personalizado utiliza para tomar las decisiones de autorización. Para obtener más detalles sobre los enlaces proporcionados por el sistema, consulte Enlaces proporcionados por el sistema.
Asocie el comportamiento con un punto de conexión de servicio. Para ello, agregue un elemento <service> y establezca el valor del atributo
behaviorConfiguration
con el valor del atributo de nombre del elemento <behavior>.Para obtener más información sobre el proceso de configuración de un punto de conexión de servicio, consulte Procedimiento para crear un punto de conexión de servicio en la configuración.
El ejemplo de código siguiente registra el administrador de autorización personalizado
Samples.MyServiceAuthorizationManager
.<configuration> <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior"> <host> <baseAddresses> <add baseAddress="http://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,MyAssembly" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
Advertencia
Tenga en cuenta que cuando se especifica el serviceAuthorizationManagerType, la cadena debe contener el nombre de tipo completo. una coma, y el nombre del ensamblado en el que el tipo está definido. Si deja fuera el nombre del ensamblado, WCF intentará cargar el tipo desde System.ServiceModel.dll.
Ejemplo
El ejemplo de código siguiente muestra una implementación básica de una clase ServiceAuthorizationManager que incluye la invalidación del método CheckAccessCore. El código de ejemplo examina AuthorizationContext para una demanda personalizada y devuelve true
cuando el recurso para esa demanda de la costumbre coincide con el valor de la acción de OperationContext. Para obtener una implementación más completa de una clase ServiceAuthorizationManager, consulte Directiva de autorización.
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 "http://www.contoso.com/claims/allowedoperation".
foreach (Claim c in cs.FindClaims("http://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;
}
}
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 "http://www.contoso.com/claims/allowedoperation".
Dim c As Claim
For Each c In cs.FindClaims("http://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