同CLR一起交付的默认策略文件,包括一套内置的代码组。如图9.4所示,注意,五个SecurityZone值的每一个都有一个截然不同的代码组,连同一个著名的带有微软和ECMA公钥的程序集组。用户定义的新代码组通常作为孩子加入到All Code组下,除非安全区域被用作成员条件的一个组成部分。
例如,对mscorLib程序集运行刚才描述的示例程序,将会产生如下输出结果:
UnionCodeGroup['AIl_Code']:FullTrust
UnionCodeGroup['AIl_Code']:Nothing
UnionCodeGroup['ECMA _Strong_Name']:FulTrust
UnionCodeGroup['My_Computer_Zone']:FullTrust
UnionCodeGroup['AIl_Code ']:Fu11Trust
注意,在第一和第二策略级别(展示于前面代码例子的第1行和第5行)中,惟一匹配的代码组是All_Code。还可以注意到All_Code将FullTrList权限集授予代码,因为第一和第三策略级别是“企业”和“用户”级别,默认来说,二者都是简单地将FullTrust授权给每一个程序集,而不管证据是什么。第二个策略级别(展示于行2~4)对应于“计算机”策略级别。在这个策略级别中,AlL_Code组没有授予权限,不过,mscorlih也和My_Computer_Zone及ECMA Strong Narne代码组成员条件相匹配,二者都授予代码FullTrust权限。
在前面的讨论里,我提到了几个内置的命名权限集。同CLR一起交付的默认策略文件包含有七个预定义的命名权限集,如表9.1所示。Nothing权限集没有授予任何权限,它被“计算机”策略层里的根代码组所使用,这就允许根代码组安全地匹配所有没有被授予任何权限的程序集。FullTrust和Everything权限集只被用于高度可信的组件。Everything显式地指定
所有已知的权限,而FullTrust权限集只是充当一个用于隐式授予任何可能权限的暗号而已,包括那些事先不知道的权限。如图9.4所示,FullTrust权限集被授予所有从本地文件系统中加载的代码。
Internet和LocalIntranet权限集都只提供一个有限制的权限子集,用于从远程文件系统或Internet上加载而来的代码。在两种情况下,只有可验证的代码才能运行,且不允许访问非托管代码。此外,对本地文件系统的访问,要求用户通过文件对话框显式地选择文件名称。Internet权限集的限制更多,因为它既不允许生成代码,也不允许读取剪贴扳里的内容或解
析DNS名字。
除了预定义的权限集外.CLR还提供了两个特殊的代码组类型,可以根据提供的证据动志生成权限集。这两个代码组是NetCodeGroup和FileCodeGroup。NetCodeGroup产生一个权限集,该权限集包含一个动态计算的WebPermission,用于授予对代码所下载站点的连接访问。FileCodeGroup生成一个权限集,这个权限集包含一个动态计算的FileIOPermission,用于授予对代码加载来源目录的只读访问。如图9.4所示,NetCodeGroup用于向来自Internet、Intranet和受信任的安全区域的代码授予Web访问极限:而FileCodeGroup则用于对来自Intranet安全区域的代码授予文件访问权。
记住这一点很重要,通过安全策略运行一个证据体,结果得到的是一个权限集。这个功能通过CodeGroup和PolicyLevel类型的Resolve方法而公开。该方法接收一个证据体,然后根据匹配的代码组返回相应的权限集,Resolve方法返回一个System.Security.Policy.Policystatement对象,它不但指明了结果权限集,PolicyStatement
Attribute还指明一个策略声明是否是排它的(exclusive)和(或)是最终级别(level final)的,参见下面的c#程序:
using System;
using Sytem.Collections;
using System.Security;
using System.Security.Policy;
class App{
static void Main(string[] argv){
string codebase=argv[0];
//构造证据
Evidence evidence=new Evidence();
evidence.AddHost(new Url(codebase));
evidence.AddHost(Zone.CreateFromUrl(codebase));
try
{
evidence.AddHost(Site.CreateFromUrl(codebase));
}
catch(ArgumentException){/*忽略*/}
//通过遍历每一级策略来解析证据
Ienumerator i=SecurityManager.PolicyHierarchy();
while(i.MoveNext()){
PolicyLevel level=(PolicyLevel)i.Current;
PolicyStatement statement=level.Resolve(evidence);
Console.writeLine(“Level:{0}(Attributes={1})”,Level.Label,statement.Attributes);
Console.WriteLine(statement.PermissionSet);
}
}
}
Resolve方法首先查找匹配的代码组,然后将每一个代码组的权限集所授予的权限合并起来。为了探明这个聚集中使用的权限,你需要对每一个权限集取交集,并将PermissionstatementAttribute.LevelFinal属性考虑进来。有幸的是,CLR通过高层次的SecurityManager.ResolvePolicy方法提供了这个功能。刚才展示的示例代码可以使用ResolvePolicy重写,如下所示:
using System;
using Sytem.Collections;
using System.Security;
using System.Security.Policy;
class App{
static void Main(string[] argv){
string codebase=argv[0];
//构造证据
Evidence ev=new Evidence();
evidence.AddHost(new Url(codebase));
evidence.AddHost(Zone.CreateFromUrl(codebase));
try{evidence.AddHost(Site.CreateFromUrl(codebase));}
catch(ArgumentException){/*ignore*/}
//从所有级别获得权限的总和
PermissionSet ps=SecurityManager.ResolvePolicy(ev);
Console.WriteLine(ps);
}
}
注意ResolvePolicy方法只返回一个权限集,而不像PolicyLevel.Resolve返回一个策略声明,这是因为仅当从多个策略级别合并权限时,才需要策略声明上的额外的Attribute属性。因为SecurityManager.ResolvePolicY已经考虑到每一个可适用的策略级别,所以除了结果权限集之外,无需再返回其他内容。
除了对每一个级别的权限真正确地进行取交集之外,SecurityManager.ResolvePolicy方法还根据提供的证据添加标识权限(identity permissions)。每一种宿主证据类型(例如,Url、Zone或StrongName)都有—个对应的权限类型。SecurityManager.ResolvePolicy遍历宿主证据列表,井从每一个支持IIdentityPermissionFactory
接口的征据中收集额外的权限。所有内置的证据类型都支持这个接口。标识权限总是由策略添加,并可用于要求调用方(一个或多个)属于一个特定的安全区域或来源于一个特定的站点。O梍wQ g儚NOCgP杽v(u7b孴鹼邁tXT鄀誰O(usQ.?`剉膥鯪0<