다음을 통해 공유


방법: 사용자 지정 권한 부여 정책 만들기

WCF(Windows Communication Foundation)의 ID 모델 인프라에서는 클레임 기반의 권한 부여 모델을 지원합니다. 클레임은 토큰에서 추출되어 사용자 지정 권한 부여 정책에 의해 선택적으로 처리된 다음,이후에 권한 부여를 결정하기 위해 검사할 수 있는 AuthorizationContext에 배치됩니다. 사용자 지정 정책은 들어오는 토큰을 응용 프로그램에서 필요로 하는 클레임으로 변환하는 데 사용할 수 있습니다. 이런 방식에서는 WCF에서 지원하는 다른 토큰 유형이 사용된 서로 다른 클레임에 대한 세부 사항이 응용 프로그램 계층에 적용되지 않을 수 있습니다. 이 항목에서는 사용자 지정 권한 부여 정책을 구현하는 방법과 이 정책을 서비스에 사용된 정책 컬렉션에 추가하는 방법에 대해 설명합니다.

사용자 지정 권한 부여 정책을 구현하려면

  1. IAuthorizationPolicy에서 파생되는 새 클래스를 정의합니다.

  2. 클래스에 대해 생성자에서 고유 문자열을 생성하고 속성에 액세스할 때마다 해당 문자열을 반환하여 읽기 전용 Id 속성을 구현합니다.

  3. 정책 발급자를 나타내는ClaimSet를 반환하여 읽기 전용 Issuer 속성을 구현합니다. 이는 응용 프로그램을 나타내는 ClaimSet이거나 기본 제공된ClaimSet(예를 들면 정적 System 속성에 의해 반환된 ClaimSet)일 수 있습니다.

  4. 다음 절차에 따라 Evaluate 메서드를 구현합니다.

Evaluate 메서드를 구현하려면

  1. 두 매개 변수인 개체 참조와 EvaluationContext 클래스의 인스턴스를 이 메서드에 전달합니다.

  2. EvaluationContext의 현재 콘텐츠에 관계없이 사용자 지정 권한 부여 정책을 통해 ClaimSet 인스턴스를 추가하려면, AddClaimSet 메서드를 호출하여 각 ClaimSet를 추가하고 Evaluate 메서드에서 true를 반환합니다. true가 반환되면 권한 부여 정책의 작업이 수행되어 이를 다시 호출할 필요가 없음을 권한 부여 인프라에 알립니다.

  3. 특정 클레임이 EvaluationContext에 이미 있는 경우에만 사용자 지정 권한 부여 정책을 통해 클레임 집합을 추가하려면 ClaimSets 속성에 의해 반환된 ClaimSet 인스턴스를 검사하여 이러한 클레임을 찾습니다. 클레임이 있으면 AddClaimSet 메서드를 호출하여 새로운 클레임 집합을 추가하고, 추가할 클레임 집합이 없으면 권한 부여 정책의 작업이 완료되었음을 권한 부여 인프라에 알리는 true를 반환합니다. 클레임이 없으면 false를 반환하는 데, 이는 다른 권한 부여 정책을 통해 클레임 집합을 EvaluationContext에 추가하려면 권한 부여 정책을 다시 호출해야 함을 알립니다.

  4. 더 복잡한 처리 시나리오에서는 Evaluate 메서드의 두 번째 매개 변수를 사용하여 상태 변수를 저장합니다. 이 상태 변수는 이후 각 호출 동안 특정 평가를 목적으로 권한 부여 인프라가 Evaluate 메서드에 다시 전달하는 변수입니다.

구성을 통해 사용자 지정 권한 부여 정책을 지정하려면

  1. serviceAuthorization 요소에서 authorizationPolicies 요소에 있는 add 요소의 policyType 특성에 사용자 지정 권한 부여 정책 유형을 지정합니다.

    <configuration>
     <system.serviceModel>
      <behaviors>
        <serviceAuthorization serviceAuthorizationManagerType=
                  "Samples.MyServiceAuthorizationManager" >
          <authorizationPolicies>       
            <add policyType="Samples.MyAuthorizationPolicy"
          </authorizationPolicies>
        </serviceAuthorization>
      </behaviors>
     </system.serviceModel>
    </configuration>
    

코드를 통해 사용자 지정 권한 부여 정책을 지정하려면

  1. IAuthorizationPolicyList을 만듭니다.

  2. 사용자 지정 권한 부여 정책의 인스턴스를 만듭니다.

  3. 권한 부여 정책 인스턴스를 목록에 추가합니다.

  4. 각 사용자 지정 권한 부여 정책에 대해 2단계와 3단계를 반복합니다.

  5. 읽기 전용 버전의 목록을 ExternalAuthorizationPolicies 속성에 할당합니다.

    ' Add custom authorization policy to service authorization behavior.
    Dim policies As List(Of IAuthorizationPolicy) = New List(Of IAuthorizationPolicy)()
    policies.Add(New MyAuthorizationPolicy())
    serviceHost.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly()
    
    // Add a custom authorization policy to the service authorization behavior.
    List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>();
    policies.Add(new MyAuthorizationPolicy());
    serviceHost.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly();
    

예제

다음 예제에서는 전체 IAuthorizationPolicy 구현을 보여 줍니다.

Public Class MyAuthorizationPolicy
    Implements IAuthorizationPolicy
    Private id_Value As String
    
    
    Public Sub New() 
        id_Value = Guid.NewGuid().ToString()
    
    End Sub 
    
    
    Public Function Evaluate(ByVal evaluationContext As EvaluationContext, ByRef state As Object) As Boolean _
        Implements IAuthorizationPolicy.Evaluate
        Dim bRet As Boolean = False
        Dim customstate As CustomAuthState = Nothing
        
        ' If the state is null, then this has not been called before, so set up
        ' our custom state.
        If state Is Nothing Then
            customstate = New CustomAuthState()
            state = customstate
        Else
            customstate = CType(state, CustomAuthState)
        End If 
        ' If claims have not been added yet...
        If Not customstate.ClaimsAdded Then
            ' Create an empty list of Claims.
            Dim claims as IList (Of Claim) = New List(Of Claim)()
            
            ' Iterate through each of the claimsets in the evaluation context.
            Dim cs As ClaimSet
            For Each cs In  evaluationContext.ClaimSets
                ' Look for Name claims in the current claimset...
                Dim c As Claim
                For Each c In  cs.FindClaims(ClaimTypes.Name, Rights.PossessProperty)
                    ' Get the list of operations that the given username is allowed to call.
                    Dim s As String
                    For Each s In  GetAllowedOpList(c.Resource.ToString())
                        ' Add claims to the list.
                        claims.Add(New Claim("http://example.org/claims/allowedoperation", s, Rights.PossessProperty))
                        Console.WriteLine("Claim added {0}", s)
                    Next s
                Next c 
            Next cs ' Add claims to the evaluation context.    
            evaluationContext.AddClaimSet(Me, New DefaultClaimSet(Me.Issuer, claims))
            
            ' Record that claims were added.
            customstate.ClaimsAdded = True
            
            ' Return true, indicating that this does not need to be called again.
            bRet = True
        Else
            ' Should never get here, but just in case...
            bRet = True
        End If
        
        
        Return bRet
    
    End Function
    
    Public ReadOnly Property Issuer() As ClaimSet Implements IAuthorizationPolicy.Issuer
        Get
            Return ClaimSet.System
        End Get
    End Property 
    
    Public ReadOnly Property Id() As String Implements IAuthorizationPolicy.Id
        Get
            Return id_Value
        End Get
    End Property 
    ' This method returns a collection of action strings thet indicate the 
    ' operations the specified username is allowed to call.
    
        ' Operations the specified username is allowed to call.
    Private Function GetAllowedOpList(ByVal userName As String) As IEnumerable(Of String)
            Dim ret As IList(Of String) = new List(Of String)()
        If username = "test1" Then
            ret.Add("http://Microsoft.ServiceModel.Samples/ICalculator/Add")
            ret.Add("http://Microsoft.ServiceModel.Samples/ICalculator/Multiply")
            ret.Add("http://Microsoft.ServiceModel.Samples/ICalculator/Subtract")
        ElseIf username = "test2" Then
            ret.Add("http://Microsoft.ServiceModel.Samples/ICalculator/Add")
            ret.Add("http://Microsoft.ServiceModel.Samples/ICalculator/Subtract")
        End If
        Return ret
     End Function
    
    ' internal class for keeping track of state
    
    Class CustomAuthState
        Private bClaimsAdded As Boolean
        
        
        Public Sub New() 
            bClaimsAdded = False
        
        End Sub 'New
        
        
        Public Property ClaimsAdded() As Boolean 
            Get
                Return bClaimsAdded
            End Get
            Set
                bClaimsAdded = value
            End Set
        End Property 
    End Class 
End Class 
public class MyAuthorizationPolicy : IAuthorizationPolicy
{
  string id;
  
  public MyAuthorizationPolicy()
  {
    id =  Guid.NewGuid().ToString();
  }

  public bool Evaluate(EvaluationContext evaluationContext, ref object state)
  {
    bool bRet = false;
    CustomAuthState customstate = null;

    // If the state is null, then this has not been called before so 
    // set up a custom state.
    if (state == null)
    {
      customstate = new CustomAuthState();
      state = customstate;
    }
    else
      customstate = (CustomAuthState)state;

    // If claims have not been added yet...
    if (!customstate.ClaimsAdded)
    {
      // Create an empty list of claims.
      IList<Claim> claims = new List<Claim>();

      // Iterate through each of the claim sets in the evaluation context.
      foreach (ClaimSet cs in evaluationContext.ClaimSets)
        // Look for Name claims in the current claimset.
        foreach (Claim c in cs.FindClaims(ClaimTypes.Name, Rights.PossessProperty))
          // Get the list of operations the given username is allowed to call.
          foreach (string s in GetAllowedOpList(c.Resource.ToString()))
          {
            // Add claims to the list.
            claims.Add(new Claim("http://example.org/claims/allowedoperation", s, Rights.PossessProperty));
            Console.WriteLine("Claim added {0}", s);
          }
      
      // Add claims to the evaluation context.
      evaluationContext.AddClaimSet(this, new DefaultClaimSet(this.Issuer,claims));
      
      // Record that claims were added.
      customstate.ClaimsAdded = true;
      
      // Return true, indicating that this method does not need to be called again.
      bRet = true;
    }
    else
    {
      // Should never get here, but just in case, return true.
      bRet = true;
    }
    
    
    return bRet;
  }

  public ClaimSet Issuer
  {
    get { return ClaimSet.System; }
  }
  
  public string Id
  {
    get { return id; }
  }

  // This method returns a collection of action strings that indicate the 
  // operations the specified username is allowed to call.
  private IEnumerable<string> GetAllowedOpList(string username)
  {
    IList<string> ret = new List<string>();
    
    if (username == "test1")
    {
      ret.Add ( "http://Microsoft.ServiceModel.Samples/ICalculator/Add");
      ret.Add ("http://Microsoft.ServiceModel.Samples/ICalculator/Multiply");
      ret.Add("http://Microsoft.ServiceModel.Samples/ICalculator/Subtract");
    }
    else if (username == "test2")
    {
      ret.Add ( "http://Microsoft.ServiceModel.Samples/ICalculator/Add");
      ret.Add ("http://Microsoft.ServiceModel.Samples/ICalculator/Subtract");
    }
    return ret;
  }

  // Internal class for keeping track of state.
  class CustomAuthState
  {
    bool bClaimsAdded;
    
    public CustomAuthState()
    {
      bClaimsAdded = false;
    }
    
    public bool ClaimsAdded { get { return bClaimsAdded; } 
    set {  bClaimsAdded = value; } }
  }
}

참고 항목

작업

방법: 클레임 비교
방법: 서비스에 대한 사용자 지정 권한 부여 관리자 만들기
권한 부여 정책

참조

ServiceAuthorizationManager