概述
Windows Communication Foundation (WCF) 是 Microsoft 为构建面向服务的应用程序而提供的统一编程模型(摘自MSDN),在分布式环境下的安全问题尤为重要,如果你觉得使用了WCF默认的安全措施可以让你高枕无忧,那明天你可就以回家种田了,当然,对于学习来说,足够了~,但我们讲的是真正的项目应用,WCF在各种协议下的安全提供和保证是不尽相同的。
背景
在上一章我们说到可以建立自定义的声明授权策略,灵活的对服务操作进行访问限制,这次嘛,我想我们还是专注在这一块上面,不过要讨论的是限制服务访问的另一种策略,即如何配置基于声明安全性的服务访问权限,本次示例主要是通过一个服务中建立三个不同的操作,还是用经典的计算器操作吧,我们将在加法上配置服务必须是windows管理员权限组的成员才可以调用服务操作,减法操作上将访问限制为windows来宾(Guest)组成员可以访问,乘法操作是任何人都可以访问的,本次示例运行在单独的计算机上,因为我们采用的安全策略为Message,在传输和消息安全上,都是启用了windows,应用还是非常简单的。等不及了吧?呵~,开锣咯~~
开始
首先来介绍一下声明安全性操作的各种级别间不同的限制,以下两张表中的数据来自MSDN。
1、声明安全性执行的安全操作(System.Security.Permissions.SecurityAction)
成员名称 说明
--------------------------------------------------------------------------------------------------------------------------------------------------
Demand 要求调用堆栈中的所有高级调用方都已被授予了当前权限对象所指定的权限。Assert 即使堆栈中的高级调用方未被授予访问当前权限对象所标识资源的权限,调用代码仍能访问该资源(请参见 使用 Assert 方法)。
Deny 即使调用方已被授予访问当前权限对象所指定资源的权限,调用方访问该资源的能力仍被拒绝(请参见 使用 Deny 方法)。
PermitOnly 即使代码已被授予访问其他资源的权限,也只能访问此权限对象所指定的资源(请参见 使用 PermitOnly 方法)。
LinkDemand 要求直接调用方已被授予了指定的权限。
InheritanceDemand 要求继承此类或重写某一方法的派生类已被授予了指定的权限。有关更多信息,请参见继承要求。
RequestMinimum 请求使代码运行所需的最小权限。此操作只能在程序集范围内使用。
RequestOptional 请求可选的附加权限(并非运行所必需的权限)。此请求隐式拒绝未明确请求的所有其他权限。此操作只能在程序集范围内使用。
RequestRefuse 请求不将可能被误用的权限授予调用代码。此操作只能在程序集范围内使用。
2、下表描述了每一个安全操作发生的时间以及支持的目标。
声明安全操作 操作时间 支持的目标
------------------------------------------------------------------------
LinkDemand 实时编译 类,方法InheritanceDemand 加载时间 类,方法
Demand 运行时 类,方法
Assert 运行时 类,方法
Deny 运行时 类,方法
PermitOnly 运行时 类,方法
RequestMinimum 授予时间 程序集
RequestOptional 授予时间 程序集
RequestRefuse 授予时间 程序集
服务代码设置
在服务中,我们首先建立三个操作:
[PrincipalPermission(SecurityAction.Demand, Role = " Administrators " , Unrestricted = false )]
public double Add( double n1, double n2)
{
return n1 + n2;
}
// 来宾用户可以访问
[PrincipalPermission(SecurityAction.Demand, Role = " Guest " )]
public double Subtract( double n1, double n2)
{
return n1 - n2;
}
// 任何用户组成员都可以访问
public double Multiply( double n1, double n2)
{
return n1 * n2;
}
1、在第一个加法操作中:设置为服务调用者必须是windows管理员权限组的成员才可以调用服务操作,并在声明安全性操作中将级别调整到SecurityAction.Demand,即要求调用堆栈中的所有高级调用方都已被授予了当前权限对象所指定的权限
2、安全性操作中将Role(角色)设置为管理员组成员角色,
3、并将是否声明了对受该属性保护的资源有完全(无限制的)权限,Unrestricted设置为false,默认也为false。
4、在减法操作中,设置与加法相同,只不过将访问此操作的成员角色调整为来宾用户组(Guest)。
5、乘法操作不设访问限制,任何用户可访问。
服务配置文件设置
1、在服务的配置文件中,我们必须要将绑定和配置进行相应的调整,代码如下:
< behavior name = " UserDataBehavior " >
< serviceMetadata httpGetEnabled = " False " />
< serviceDebug includeExceptionDetailInFaults = " True " />
< serviceCredentials >
< serviceCertificate findValue = " 192168168151service "
x509FindType = " FindBySubjectName "
storeLocation = " LocalMachine "
storeName = " My " />
serviceCredentials >
< serviceAuthorization principalPermissionMode = " UseWindowsGroups " />
behavior >
// 绑定配置
< binding name = " EndpointBinding " >
< security mode = " Message " >
< transport clientCredentialType = " Windows " protectionLevel = " EncryptAndSign " />
< message clientCredentialType = " Windows " />
security >
binding >
2、在服务绑定中,将安全策略调整为消息模式,将在传输和消息安全中启用windows级别。
3、在服务配置中(红色部分),将声明的执行授权检查的模式设为:
客户端调用
1、在下面,我们分别使用管理员用户来调用相应的服务操作,并将结果打印到控制台,代码如下:
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( " 嘎嘎,我是分割线----------------------------------------------------------------- " );
client = new UserDataClient();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine( " Administrators成员访问 " );
double Addresult = client.Add( 10 , 20 );
Console.WriteLine( " Addresult:{0}+{1}={2} " , 10 , 20 , Addresult);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( " 嘎嘎,我是分割线----------------------------------------------------------------- " );
client = new UserDataClient();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine( " Guest成员访问 " );
double Subtractresult = client.Subtract( 30 , 20 );
Console.WriteLine( " Subtractresult:{0}-{1}={2} " , 30 , 20 , Subtractresult);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( " 嘎嘎,我是分割线----------------------------------------------------------------- " );
client = new UserDataClient();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine( " Multiplyresult正常访问 " );
double Multiplyresult = client.Multiply( 10 , 20 );
Console.WriteLine( " Multiplyresult:{0}*{1}={2} " , 10 , 20 , Multiplyresult);
2、因为目前使用的是管理员组的用户调用服务,所以在调用减法的时候,会抛出一个异常,我们在这里也捕获一下,给大家一个直观的印象.
3、在这里特别声明一下,并不是管理员就比来宾角色权限高,这点与操作系中建立用户时分配的权限没有关系。我们来看服务调用结果。
========================================================
后话:随便扯点啦 ,哈哈,别介意。
1、如果在服务器将服务验证设置为:
2、在需要启用安全检查的方法中加上如下代码: [PrincipalPermission(SecurityAction.Demand, Role = "Users")]SecurityAction:代表权限检查级别Role:所使用的windows组的名称,一般可以设为Administartor或者Guest(这里不包括使用UseAspNetRoles)
3、在调用服务时,默认使用的是当前系统登陆用户,与客户端设置的用户名密码没啥关系,如:
client.ClientCredentials.UserName.UserName = "Guest";
client.ClientCredentials.UserName.Password = "admin";相当于无效代码。
4、System.Security.Permissions命名空间下包含了根据策略定义控制对操作和资源访问的类,这些类可以让我们很好根据业务的需要对程序代码访问进行灵活的控制。
------------------------------------------------------------------------------------------------------------------------------------------------
欢迎转载,但请注明出处--lsotcode博客(http://www.cnblogs.com/viter/)!
说得不对的地方,欢迎拍砖!