任务 2:对工作流服务启用基于声明的授权
在此任务中,要确保只有一组用户凭据可以对您在练习 1:创建基本工作流服务中创建的工作流服务调用操作。这些凭据以 ClaimSet 的形式传递到服务。有关 ClaimSet 的更多信息,请参见Managing Claims and Authorization with the Identity Model。
提示
使用 Visual Studio 工作流设计器创建或管理工作流服务时,该设计器有时会产生虚假的验证错误。如果可以成功地生成项目,请忽略验证错误。
通过 ClaimSet 启用用户验证
如果当前没有打开 WorkflowServiceTutorial 解决方案,请打开 Visual Studio 2008,单击**“文件”,突出显示“打开”**,并导航到 WorkflowServiceTutorial 解决方案。
在**“解决方案资源管理器”窗格中的 WorkflowServiceTutorial 项目节点下,右击“引用”子文件夹,然后选择“添加引用”。或者,如果您创建了 Visual Basic 解决方案,请右击 WorkflowServiceTutorial 项目节点,然后选择“添加引用”**。
在**“添加引用”对话框中,在“NET”选项卡下选择“System.IdentityModel”,然后单击“确定”**。
此任务使用 ClaimSet 和 List 对象,因此,请使用 Workflow1.cs 顶部的语句添加以下内容:
using System.IdentityModel.Claims; using System.Collections.Generic;
如果您创建了 Visual Basic 解决方案,请右击 WorkflowServiceTutorial 项目节点,然后选择**“属性”。选择“引用”选项卡,然后在“导入的命名空间”**下单击 System.IdentityModel.Claims 的复选框。System.Collections.Generic 命名空间已经受支持。
如果工作流服务的工作流设计器不可见,请右击 Workflow1.cs(如果您创建了 Visual Basic 解决方案,则右击 Workflow1.vb)打开该设计器,并选择**“视图设计器”**。
在 Workflow1InitialState StateActivity 活动中,双击 WaitToStartService EventDrivenActivity 活动以展开该复合活动。
突出显示与 StartupService 操作相关联的 ReceiveActivity 活动。
在**“属性”窗格中的“OperationValidation”**下,键入 ValidateUser 并按 Enter,以自动生成 OperationValidation 事件的事件处理程序。
导航到 ValidateUser 事件处理程序。
在 ValidateUser 的正文中,验证服务以前是否已经识别了用户,如果未识别,则不要让他们调用任何操作。例如,如果销售雇员启动订单并且直到几天以后才返回完成它,则这非常有用。在让用户对服务调用任何其他操作之前,应该验证是否是同一用户。因为恶意用户可能会模仿对话和上下文 ID,所以不能使用对话和上下文 ID。
Private Sub ValidateUser(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.OperationValidationEventArgs) For Each claims As ClaimSet In e.ClaimSets ' Find the claim that contains the name of the operation caller. Dim opCaller As List(Of Claim) = claims.FindClaims(ClaimTypes.Name, Rights.PossessProperty).ToList() ' Retrieve the name of the caller from the claim. Dim opCallerName As String = opCaller(0).Resource.ToString() ' If this is the caller's first time through the ValidationUser method, set ' the operation caller's name to a global variable named "owner." Every subsequent ' operation that uses this method will verify that the caller of ' the operation is the same as the caller of the initial operation before ' either validating or invalidating the caller. If [String].IsNullOrEmpty(owner) Then owner = opCallerName ElseIf Not owner.Equals(opCallerName) Then e.IsValid = False End If Next End Sub
private void ValidateUser(object sender, OperationValidationEventArgs e) { foreach (ClaimSet claims in e.ClaimSets) { // Find the claim that contains the name of the operation caller. List<Claim> opCaller = claims.FindClaims(ClaimTypes.Name, Rights.PossessProperty).ToList<Claim>(); // Retrieve the name of the caller from the claim. string opCallerName = opCaller[0].Resource.ToString(); // If this is the caller's first time through the ValidationUser method, set // the operation caller's name to a global variable named "owner." Every subsequent // operation that uses this method will verify that the caller of // the operation is the same as the caller of the initial operation before // either validating or invalidating the caller. if(String.IsNullOrEmpty(owner)) { owner = opCallerName; } else if (!owner.Equals(opCallerName)) { e.IsValid = false; } } }
声明一个名为“owner”的变量以在接收后续操作调用时用于验证,如以下代码所示:
Public class ServerWorkflow Inherits StateMachineWorkflowActivity ' These variables are bound to the input and output parameters of the ReceiveActivity. Public returnValue As Int32 = Nothing Public inputValue As Int32 = Nothing 'This variable contains the user name for the NT account used in operation validation. Public owner As String = Nothing ... End Class
public sealed partial class ServerWorkflow : StateMachineWorkflowActivity { public ServerWorkflow() { InitializeComponent(); } // These variables are bound to the input and output parameters of the ReceiveActivity. public int returnValue = default(int); public int inputValue = default(int); // This variable contains the user name for the NT account used // in operation validation. public string owner = default(string); ... }
对于其余每个操作,将 OperationValidation 事件与 ValidateUser 方法相关联。
生成您的解决方案并验证您的授权检查是否起作用。
如果在设置 owner 变量后具有不同用户名的用户尝试对服务调用操作,则会将以下错误消息返回到客户端:
Security check failed.
提示
ClaimSet 在 PrincipalPermissionRole 或 PrincipalPermissionName 之前得到处理,因此,如果您对 NT 帐户组执行两项不同的授权检查(一项使用 ClaimSet,另一项使用 PrincipalPermissionRole),则 ClaimSet 授权检查将首先进行。
另请参见
任务
其他资源
版权所有 (C) 2007 Microsoft Corporation。保留所有权利。