Crear un atributo de autorización personalizado
En este tema se muestra cómo agregar un atributo personalizado para la autorización. El marco de WCF RIA Services proporciona los atributos RequiresRoleAttribute y RequiresAuthenticationAttribute. Estos atributos permiten especificar fácilmente qué operaciones de dominio solo están disponibles para los usuarios autenticados o para los usuarios pertenecientes a un rol concreto. Además de estos dos atributos, se puede crear un atributo que represente la lógica de autorización personalizada y aplicarlo después a las operaciones de dominio.
Cuando se expone un servicio de dominio, este servicio de dominio está disponible para todos los usuarios en la red. No se puede suponer que una aplicación cliente propia es la única aplicación que tendrá acceso al servicio de dominio. Se pueden utilizar atributos de autenticación personalizados para restringir el acceso a las operaciones de dominio aun cuando se tenga acceso a la operación de dominio desde fuera de la aplicación cliente.
En este tema creará un atributo de autorización personalizado mediante la creación de una clase que deriva de AuthorizationAttribute y el reemplazo del método IsAuthorized para proporcionar la lógica personalizada propia. Puede utilizar los parámetros IPrincipal y AuthorizationContext para tener acceso a información que pueda necesitar dentro de su código de autenticación personalizado. El objeto AuthorizationContext es null en operaciones de consulta.
Para crear un atributo de autorización personalizado
En el proyecto de servidor, cree una clase que derive de AuthorizationAttribute.
Reemplace el método IsAuthorized y agregue lógica para determinar la autorización.
En el ejemplo siguiente se muestra un atributo personalizado denominado
RestrictAccessToAssignedManagers
que comprueba si el usuario autenticado es el superior del empleado cuyo registro deEmployeePayHistory
se está modificando.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."); } } }
Para realizar la lógica de autorización personalizada, aplique el atributo de autorización personalizado a la operación de dominio.
En el ejemplo siguiente se muestra el atributo
RestrictAccessToAssignedManagers
aplicado a una operación de dominio.<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); } }