工作流程第一和安全性範例

這個範例示範工作流程服務中的兩項關鍵功能:

  • 撰寫服務的「工作流程第一」方法
    使用工作流程撰寫服務時,您可以在兩種方式中選用一個。一個是「合約第一」撰寫方式,適用於合約已經存在,且工作流程會實作合約的情況。另一個則是「工作流程第一」,此方式會在撰寫工作流程時建立合約。工作流程設計工具的運作方式,實際上就和合約設計工具一樣。在這個範例中,計算機合約即是在撰寫工作流程時建立的。
    此範例會在 SequentialCalculatorService.xoml 檔案中實作「工作流程第一」標記。若要瞭解「工作流程第一」程式設計背後的程式設計模型,請將此標記與其他工作流程範例的標記做比較。
    下列範例程式碼會顯示範例中 Receive 活動的標記。

    <ns0:ReceiveActivity x:Name="ReceiveAdd" OperationValidation="ValidateOwner" CanCreateInstance="True">
    <ns0:ReceiveActivity.ServiceOperationInfo>
            <ns0:OperationInfo PrincipalPermissionRole="Administrators" Name="Add" ContractName="ICalculator">
                <ns0:OperationInfo.Parameters>
                              <ns0:OperationParameterInfo Attributes="In" ParameterType="{x:Type p15:Int32}" Name="value" Position="0" 
                                       xmlns:p15="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
                                       <ns0:OperationParameterInfo Attributes="Out" ParameterType="{x:Type p15:Int32}" Name="returnValue" Position="1" 
                                       xmlns:p15="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
                </ns0:OperationInfo.Parameters>
            </ns0:OperationInfo>
    </ns0:ReceiveActivity.ServiceOperationInfo>
        <ns0:ReceiveActivity.ParameterBindings>
            <WorkflowParameterBinding ParameterName="value">
                <WorkflowParameterBinding.Value>
                    <ActivityBind Name="SequentialCalculatorService" Path="inputValue" />
                </WorkflowParameterBinding.Value>
            </WorkflowParameterBinding>
            <WorkflowParameterBinding ParameterName="returnValue">
                <WorkflowParameterBinding.Value>
                    <ActivityBind Name="SequentialCalculatorService" Path="currentValue" />
                </WorkflowParameterBinding.Value>
            </WorkflowParameterBinding>
        </ns0:ReceiveActivity.ParameterBindings>
        <CodeActivity x:Name="DoAdd" ExecuteCode="Add" />
    </ns0:ReceiveActivity>
    

    「接收」活動不包含外部合約類型的參考,而合約則是定義在 Receive 活動本身之中。「接收」活動中的 OperationInfo 區塊會一併描述合約名稱和作業名稱。這些名稱是常值字串,不含定義合約之類型的任何參考。
    當您執行範例時,工作流程服務主機會使用這個定義來建立服務描述。若要為此建立服務用戶端,請使用 ServiceModel Metadata Utility Tool (Svcutil.exe)

  • 工作流程服務中的安全性
    工作流程服務可以為服務提供兩種安全性層級。在第一個層級中,您會在作業上指定原則權限安全性。服務執行階段會在傳遞訊息至工作流程之前檢查權限。如果訊息不符合原則權限安全性,就不會將訊息傳遞至工作流程。第二個層級是可指派給「接收」活動的「作業驗證條件」。當「接收」活動接收訊息時,會執行作業驗證條件。如果訊息不符合作業驗證條件,便會將錯誤傳送給用戶端、刪除訊息,然後指出工作流程發生錯誤。
    OperationInfo 項目上的 PrincipalPermissionRole 屬性會指定只允許 Administrators 群組中的使用者呼叫這項作業。
    「接收」活動上的 OperationValidation 屬性會指向要當做驗證條件執行的程式碼處理常式。在這個範例中,因為在第一個「接收」活動上設定了 PrincipalPermissionRole 屬性,所以只有 Administrators 群組中的使用者可以叫用第一項作業。在這個工作流程中,ReceiveAdd 接收活動具有設定為 trueCanCreateInstance 屬性。這表示會在 Administrators 群組的使用者呼叫「新增」作業時,建立此服務的執行個體。
    在後續的「接收」作業中,OperationValidation 條件會進行檢查,以確定叫用作業的主體與建立執行個體的主體是同一個。在此案例中,只有初始化執行個體的人才可以傳送其他訊息。下列範例顯示執行此項作業之 OperationValidation 條件中的程式碼。

    private void ValidateOwner(object sender, OperationValidationEventArgs e)
    {
        if (string.IsNullOrEmpty(owner))
        {
            owner = ExtractCallerName(e.ClaimSets);
            e.IsValid = true;
            Console.WriteLine("Owner: " + owner);
        }
        if (owner.Equals(ExtractCallerName(e.ClaimSets)))
            e.IsValid = true;
    }
    private string ExtractCallerName(ReadOnlyCollection<ClaimSet> claimSets)
    {
        string owner = string.Empty;
        foreach (ClaimSet claims in claimSets)
        {
            foreach (Claim claim in claims)
            {
                if (claim.ClaimType.Equals(ClaimTypes.Name) && 
                     claim.Right.Equals(Rights.PossessProperty))
                {
                    owner = claim.Resource.ToString();
                    break;
                }
            }
        }
        return owner;
    }
    

    所顯示的 ValidateOwner 方法提供了宣告集做為 OperationValidationEventArgs 引數的一部分。它會使用這些宣告集,完成訊息驗證。請注意,此時還不能使用實際的訊息本文參數。ExtractCallerName 方法會從名稱宣告擷取呼叫者名稱,然後加以儲存。在後續要求中,會根據傳入訊息的名稱宣告檢查呼叫者名稱,以確認傳送第一則訊息 (並促使建立執行個體) 的人與傳送後續訊息的人是否為同一人。

Bb410773.note(zh-tw,VS.90).gif注意:
要建置和執行這個範例,必須安裝 .NET Framework version 3.5。要開啟專案和方案檔,必須要有 Visual Studio 2008。

設定、建置及執行專案

  1. 執行 Windows Communication Foundation 範例的單次安裝程序中的安裝指示。

  2. 執行位於 Windows Communication Foundation 範例的單次安裝程序主題中的 CreateStores.cmd 指令碼。

  3. 建置方案。

    以 Administrators 群組中的使用者身分執行範例。先啟動服務可執行檔,然後再啟動用戶端可執行檔。如果您正在使用 Windows Vista,請以滑鼠右鍵按一下可執行檔,然後按一下 [以系統管理員身分執行]。將範例一直執行到完成為止。

    嘗試使用不同的使用者身分識別來執行範例 (使用 [執行身分] 命令,以不同身分識別來執行)。如果身分識別不屬於 Administrators 群組,服務便會傳回錯誤。

在不同的電腦上執行範例

  1. 編輯服務及用戶端的組態檔,並確定您已變更端點位址中的伺服器名稱。將伺服器名稱從 localhost 變更為要執行服務的電腦名稱。

  2. 服務會使用連接埠 8888,因此必須在防火牆中開啟這個連接埠。請按一下 Windows [控制台] 中的 [Windows 防火牆],再按一下 [新增連接埠],然後新增連接埠 8888。或者,您也可以在預設的連接埠上執行服務。若要這麼做,請從端點位址中移除 :8888

  3. 編輯用戶端組態檔,並將下列項目新增為 <endpoint> 項目的子項目。

    <identity>
        <UserPrincipalName value=”*@<Domain Name in which your server is running” />
    </identity>
    

    若要判斷網域名稱,請在您要執行服務的電腦上啟動服務。在別台電腦上的命令提示字元視窗中,執行下列命令。

    svcutil.exe http://<serverName>:8888/servicehost/Calculator.svc

    這個命令會產生 .cs 檔案和 output.config 檔案。在該組態檔的 <endpoint> 項目中,將 <identity> 項目複製到您的用戶端組態檔。

Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.