次の方法で共有


方法: カスタム承認属性を作成する

ここでは、承認のためのカスタム属性を追加する方法について説明します。WCF RIA サービス フレームワークには、RequiresAuthenticationAttribute 属性と RequiresRoleAttribute 属性が用意されています。これらの属性を使用すると、認証されているユーザーまたは特定の役割が割り当てられているユーザーのみが使用できるドメイン操作を容易に指定できます。この 2 つの属性に加えて、カスタマイズされた承認ロジックを表す属性を作成し、ドメイン操作に適用することができます。

ドメイン サービスを公開すると、ネットワーク上のすべてのユーザーがそのドメイン サービスを利用できます。クライアント アプリケーションがドメイン サービスにアクセスする唯一のアプリケーションとは限りません。クライアント アプリケーションの外部からドメイン操作にアクセスされる場合でも、カスタマイズされた認証属性を使用して、ドメイン操作へのアクセスを制限できます。

ここでは、カスタマイズされたロジックを提供するために、AuthorizationAttribute から派生するクラスを作成し、IsAuthorized メソッドをオーバーライドして、カスタム承認属性を作成します。IPrincipal パラメーターと AuthorizationContext パラメーターを使用して、カスタマイズされた認証コード内で必要になる可能性がある情報にアクセスできます。AuthorizationContext オブジェクトは、クエリ操作では null になります。

カスタマイズされた承認属性を作成するには

  1. サーバー プロジェクトで、AuthorizationAttribute から派生するクラスを作成します。

  2. IsAuthorized メソッドをオーバーライドし、承認を判断するロジックを追加します。

    次の例は、RestrictAccessToAssignedManagers という名前のカスタム属性を示しています。この属性は、認証されているユーザーが、変更している EmployeePayHistory レコードの対象従業員の上司であるかどうかを確認します。

    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. カスタマイズされた承認ロジックを実行するには、ドメイン操作にカスタム承認属性を適用します。

    次の例は、ドメイン操作に適用された RestrictAccessToAssignedManagers 属性を示しています。

    <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);
        }
    }