Procédure : Créer un attribut d'autorisation personnalisé

Cette rubrique montre comment ajouter un attribut personnalisé pour l'autorisation. L'infrastructure des Services RIA WCF fournit les attributs RequiresAuthenticationAttribute et RequiresRoleAttribute. Ces attributs vous permettent de spécifier facilement les opérations de domaine disponibles uniquement aux utilisateurs authentifiés ou aux utilisateurs d'un rôle particulier. En plus des ces deux attributs, vous pouvez créer un attribut qui représente une logique d'autorisation personnalisée, puis appliquer cet attribut aux opérations de domaine.

Quand vous exposez un service de domaine, celui-ci est disponible à tout le monde sur le réseau. Vous ne pouvez pas supposer que votre application cliente sera la seule à accéder au service de domaine. Vous pouvez utiliser des attributs d'authentification personnalisés pour limiter l'accès aux opérations de domaine même si l'opération de domaine est accessible en dehors de votre application cliente.

Dans cette rubrique, vous allez créer un attribut d'autorisation personnalisé en créant une classe qui dérive de AuthorizationAttribute et en substituant la méthode IsAuthorized pour fournir votre logique personnalisée. Vous pouvez utiliser le paramètre IPrincipal et le paramètre AuthorizationContext pour accéder aux informations d'accès exigées, le cas échéant, par votre code d'authentification personnalisé. L'objet AuthorizationContext est Null sur les opérations de requête.

Pour créer un attribut d'autorisation personnalisé

  1. Dans le projet serveur, créez une classe qui dérive de AuthorizationAttribute.

  2. Substituez la méthode IsAuthorized et ajoutez la logique de détermination de l'autorisation.

    L'exemple suivant montre un attribut personnalisé nommé RestrictAccessToAssignedManagers qui vérifie si l'utilisateur authentifié est le directeur de l'employé dont l'enregistrement EmployeePayHistory est modifié.

    Public Class RestrictAccessToAssignedManagers
        Inherits AuthorizationAttribute
    
        Protected Overrides Function IsAuthorized(ByVal principal As System.Security.Principal.IPrincipal, ByVal authorizationContext As System.ComponentModel.DataAnnotations.AuthorizationContext) As System.ComponentModel.DataAnnotations.AuthorizationResult
            Dim eph As EmployeePayHistory
            Dim selectedEmployee As Employee
            Dim authenticatedUser As Employee
    
            eph = CType(authorizationContext.Instance, EmployeePayHistory)
    
            Using context As New AdventureWorksEntities()
                selectedEmployee = context.Employees.SingleOrDefault(Function(e) e.EmployeeID = eph.EmployeeID)
                authenticatedUser = context.Employees.SingleOrDefault(Function(e) e.LoginID = principal.Identity.Name)
            End Using
    
            If (selectedEmployee.ManagerID = authenticatedUser.EmployeeID) Then
                Return AuthorizationResult.Allowed
            Else
                Return New AuthorizationResult("Only the authenticated manager for the employee can add a new record.")
            End If
        End Function
    End Class
    
    public class RestrictAccessToAssignedManagers : AuthorizationAttribute
    {
        protected override AuthorizationResult IsAuthorized(System.Security.Principal.IPrincipal principal, AuthorizationContext authorizationContext)
        {
            EmployeePayHistory eph = (EmployeePayHistory)authorizationContext.Instance;
            Employee selectedEmployee;
            Employee authenticatedUser;
    
            using (AdventureWorksEntities context = new AdventureWorksEntities())
            {
                selectedEmployee = context.Employees.SingleOrDefault(e => e.EmployeeID == eph.EmployeeID);
                authenticatedUser = context.Employees.SingleOrDefault(e => e.LoginID == principal.Identity.Name);
            }
    
            if (selectedEmployee.ManagerID == authenticatedUser.EmployeeID)
            {
                return AuthorizationResult.Allowed;
            }
            else
            {
                return new AuthorizationResult("Only the authenticated manager for the employee can add a new record.");
            }
        }
    }
    
  3. Pour effectuer la logique d'autorisation personnalisée, appliquez l'attribut d'autorisation personnalisé à l'opération de domaine.

    L'exemple suivant montre l'attribut RestrictAccessToAssignedManagers appliqué à une opération de domaine.

    <RestrictAccessToAssignedManagers()> _
    Public Sub InsertEmployeePayHistory(ByVal employeePayHistory As EmployeePayHistory)
        If ((employeePayHistory.EntityState = EntityState.Detached) _
                    = False) Then
            Me.ObjectContext.ObjectStateManager.ChangeObjectState(employeePayHistory, EntityState.Added)
        Else
            Me.ObjectContext.EmployeePayHistories.AddObject(employeePayHistory)
        End If
    End Sub
    
    [RestrictAccessToAssignedManagers]
    public void InsertEmployeePayHistory(EmployeePayHistory employeePayHistory)
    {
        if ((employeePayHistory.EntityState != EntityState.Detached))
        {
            this.ObjectContext.ObjectStateManager.ChangeObjectState(employeePayHistory, EntityState.Added);
        }
        else
        {
            this.ObjectContext.EmployeePayHistories.AddObject(employeePayHistory);
        }
    }