共用方式為


HOW TO:為服務建立自訂授權管理員

Windows Communication Foundation (WCF) 中的「身分識別模型」基礎結構支援可延伸的宣告授權模型。從語彙基元擷取的宣告可以選擇性地由自訂授權原則進行處理並放入 AuthorizationContext。授權管理員會檢查 AuthorizationContext 中的宣告來做出授權決策。

根據預設,ServiceAuthorizationManager 類別會做出授權決策,不過,您也可以建立自訂的授權管理員來覆寫這些決策。若要建立自訂的授權管理員,請建立衍生自 ServiceAuthorizationManager 的類別,然後實作 CheckAccessCore 方法。授權決策會在 CheckAccessCore 方法中進行,並在授與存取權時傳回 true,在拒絕存取權時傳回 false

如果授權決策取決於訊息本文的內容,則使用 CheckAccess 方法。

基於效能考量,如果可以,您應該重新設計應用程式,讓授權決策不需要存取訊息本文。

您也可以透過程式碼或組態,為服務註冊自訂授權管理員。

若要建立自訂授權管理員

  1. ServiceAuthorizationManager 類別衍生類別。

    Public Class MyServiceAuthorizationManager
        Inherits ServiceAuthorizationManager
    
    
    public class MyServiceAuthorizationManager : ServiceAuthorizationManager
    {
    
  2. 覆寫 CheckAccessCore 方法。

    使用傳遞至 CheckAccessCore 方法的 OperationContext 來做出授權決策。

    下列程式碼範例使用 FindClaims 方法來找出自訂宣告 https://www.contoso.com/claims/allowedoperation,以便做出授權決策。

    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 "https://www.contoso.com/claims/allowedoperation".
                Dim c As Claim
                For Each c In  cs.FindClaims("https://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 
    
    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 "https://www.contoso.com/claims/allowedoperation".
            foreach (Claim c in cs.FindClaims("https://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;                 
    }
    

若要使用程式碼來註冊自訂授權管理員

  1. 建立自訂授權管理員的執行個體,然後將它指派給 ServiceAuthorizationManager 屬性。

    ServiceAuthorizationBehavior 可以透過使用 Authorization 屬性來存取。

    下列程式碼範例會註冊 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();
    

若要使用組態來註冊自訂授權管理員

  1. 開啟服務的組態檔。

  2. serviceAuthorization element 新增至 Behaviors element

    針對 serviceAuthorization element 新增 serviceAuthorizationManagerType 屬性,並將它的值設定為代表自訂授權管理員的型別。

  3. 新增繫結,以便保護用戶端與服務之間的通訊安全。

    選定用在此通訊上的繫結會決定新增至 AuthorizationContext 的宣告,而自訂授權管理員會使用此宣告來做出授權決策。如需系統提供之繫結的詳細資訊,請參閱系統提供的繫結

  4. 藉由新增 <service> 項目,建立行為與服務端點的關聯,然後將 behaviorConfiguration 屬性的值設定為 <behavior> of <serviceBehaviors> 項目的名稱屬性值。

    如需設定服務端點的詳細資訊,請參閱 HOW TO:在組態中建立服務端點

    下列程式碼範例會註冊自訂授權管理員 Samples.MyServiceAuthorizationManager

    <configuration>
      <system.serviceModel>
        <services>
          <service 
              name="Microsoft.ServiceModel.Samples.CalculatorService"
              behaviorConfiguration="CalculatorServiceBehavior">
            <host>
              <baseAddresses>
                <add baseAddress="https://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" />
            </behaviors>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>
    

範例

下列程式碼範例示範包含覆寫 CheckAccessCore 方法的基本 ServiceAuthorizationManager 類別實作。此範例程式碼會檢查自訂宣告的 AuthorizationContext,並在該自訂宣告符合來自 OperationContext 的動作值時傳回 true。如需更完整的 ServiceAuthorizationManager 類別實作,請參閱授權原則

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 "https://www.contoso.com/claims/allowedoperation".
                Dim c As Claim
                For Each c In  cs.FindClaims("https://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 
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 "https://www.contoso.com/claims/allowedoperation".
          foreach (Claim c in cs.FindClaims("https://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;                 
  }
}

另請參閱

工作

授權原則
授權原則

參考

ServiceAuthorizationManager