共用方式為


作法:為服務建立自訂授權管理員

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

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

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

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

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

若要建立自訂授權管理員

  1. ServiceAuthorizationManager 類別衍生類別。

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

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

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

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

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

  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> 新增至 <behaviors>

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

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

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

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

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

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

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

    警告

    請注意,當您指定 serviceAuthorizationManagerType 時,字串必須包含完整的型別名稱。 逗號和已定義型別之組件的名稱。 如果您省略組件名稱,WCF 會嘗試從 System.ServiceModel.dll 載入型別。

範例

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

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 "http://www.contoso.com/claims/allowedoperation".
          foreach (Claim c in cs.FindClaims("http://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;
  }
}

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

另請參閱