最近学习CAS的一点总结
1 using System;
2 using System.IO;
3 using System.Security;
4 using System.Security.Permissions;
5
6 namespace Bee
7 {
8 [FileIOPermission(SecurityAction.Deny,Read=@"d:\")]
9 class Test
10 {
11 static void Main(string []args)
12 {
13 Test test = new Test();
14 test.TestForCAS();
15 }
16 public void TestForCAS()
17 {
18 try
19 {
20 FileIOPermission myPerm =
21 new FileIOPermission(FileIOPermissionAccess.Read,@"d:\");
22 //myPerm.Demand();
23
24 if(File.Exists(@"d:\11.html"))
25 {
26 Console.WriteLine("Exsist!");
27 }
28 else
29 {
30 Console.WriteLine("Not Exsist!");
31 }
32 }
33 catch(Exception ex)
34 {
35 Console.WriteLine(ex.Message);
36 }
38 }
39 }
40 }
对于上面的结果:Not Exsist!(一切都基于用户机上有D:\11.html)2 using System.IO;
3 using System.Security;
4 using System.Security.Permissions;
5
6 namespace Bee
7 {
8 [FileIOPermission(SecurityAction.Deny,Read=@"d:\")]
9 class Test
10 {
11 static void Main(string []args)
12 {
13 Test test = new Test();
14 test.TestForCAS();
15 }
16 public void TestForCAS()
17 {
18 try
19 {
20 FileIOPermission myPerm =
21 new FileIOPermission(FileIOPermissionAccess.Read,@"d:\");
22 //myPerm.Demand();
23
24 if(File.Exists(@"d:\11.html"))
25 {
26 Console.WriteLine("Exsist!");
27 }
28 else
29 {
30 Console.WriteLine("Not Exsist!");
31 }
32 }
33 catch(Exception ex)
34 {
35 Console.WriteLine(ex.Message);
36 }
38 }
39 }
40 }
而我们将myPerm.Demand();的注释放开,得到一个安全异常。
若我们将myPerm.Demand();换成myPerm.Assert();得到结果是Exsist!
我们来分析这些现象的原因。
首先我们这个程序运行时,可以根据当前程序的Evidence可知
他具有Zone(mycompute),url(程序路径),hash(程序的hash)属性。
这时根据.net的默认的安全策略,这个程序拥有fulltrust的权限。(本人推荐 代码访问安全的实践 可以帮你更好的理解)。
首先我们来看.net框架中对bool File.Exists(string path) 函数的定义:
1 public static bool Exists(string path)
2 {
3 try
4 {
5 if (path == null)
6 {
7 return false;
8 }
9 if (path.Length == 0)
10 {
11 return false;
12 }
13 path = Path.GetFullPathInternal(path);
14 new FileIOPermission(FileIOPermissionAccess.Read, new string[] { path }, false, false).Demand();
15 return File.InternalExists(path);
16 }
17 catch (ArgumentException)
18 {
19 }
20 catch (NotSupportedException)
21 {
22 }
23 catch (SecurityException)
24 {
25 }
26 catch (IOException)
27 {
28 }
29 catch (UnauthorizedAccessException)
30 {
31 }
32 return false;
33 }
34
35
上面标红的语句就是.net的CAS的具体实现方式。他在底层代码中重新调用Demand来检查当前代码的权限集,若无,就抛出安全异常。2 {
3 try
4 {
5 if (path == null)
6 {
7 return false;
8 }
9 if (path.Length == 0)
10 {
11 return false;
12 }
13 path = Path.GetFullPathInternal(path);
14 new FileIOPermission(FileIOPermissionAccess.Read, new string[] { path }, false, false).Demand();
15 return File.InternalExists(path);
16 }
17 catch (ArgumentException)
18 {
19 }
20 catch (NotSupportedException)
21 {
22 }
23 catch (SecurityException)
24 {
25 }
26 catch (IOException)
27 {
28 }
29 catch (UnauthorizedAccessException)
30 {
31 }
32 return false;
33 }
34
35
至此,对于上述现象就可以解释了吧。
1。由于类具有[FileIOPermission(SecurityAction.Deny,Read=@"d:\")]属性,所以 if(File.Exists(@"d:\11.html"))返回false,但不抛异常。
2。这个就是很正常的一个表现了。对于IPermission.Demand的实现,下面也将探讨一下
3。这个就是IPermission.Assert()的功能了。他能阻止CAS的定义的权限,但是无法阻止系统安全策略的权限。比如,根据系统安全策略 (包含企业,计算机,用户,应用程序域),当前程序只不具有访问C:的readFileIOPermission权限,你若用
1 FileIOPermission myPerm =
2 new FileIOPermission(FileIOPermissionAccess.Read,@"c:\");
3 myPerm.Assert();
2 new FileIOPermission(FileIOPermissionAccess.Read,@"c:\");
3 myPerm.Assert();
代码时,是无法获得c盘的访问权限的。具体原因也可在 代码访问安全的实践 找到。
我们再来看看FileIOPermission.Demand();的实现方法
还有具体很多代码,大伙可以具体研究,限于资料有限,也只能猜他的大概模型
(只针对CodeAccessSecurity),首先他有个跟代码栈有关的权限列表,程序栈最下面应该有个Fulltrust的权限,到了栈[FileIOPermission(SecurityAction.Deny,Read=@"d:\")]这里时权限就只有Fulltrust 去掉 FileIOPermission(FileIOPermissionAccess.Read,"d:\") 的权限。调起demand命令时,发现并无 FileIOPermission(FileIOPermissionAccess.Read,"d:\")权限,抛出异常。
我们再来看看FileIOPermission.Demand();的实现方法
1 public void Demand()
2 {
3 CodeAccessSecurityEngine engine1 = SecurityManager.GetCodeAccessSecurityEngine();
4 if ((engine1 != null) && !this.IsSubsetOf(null))
5 {
6 StackCrawlMark mark1 = StackCrawlMark.LookForMyCallersCaller;
7 engine1.Check(this, ref mark1);
8 }
9 }
10
11 //这是CodeAccessSecurityEngine 的Check方法
12
13 internal virtual void Check(CodeAccessPermission cap, ref StackCrawlMark stackMark)
14 {
15 if (!this.PreCheck(cap, null, 1, ref stackMark, PermissionType.DefaultFlag))
16 {
17 this.Check(PermissionToken.GetToken(cap), cap, ref stackMark, -1, (cap is IUnrestrictedPermission) ? 1 : 0);
18 }
19 }
20
21
2 {
3 CodeAccessSecurityEngine engine1 = SecurityManager.GetCodeAccessSecurityEngine();
4 if ((engine1 != null) && !this.IsSubsetOf(null))
5 {
6 StackCrawlMark mark1 = StackCrawlMark.LookForMyCallersCaller;
7 engine1.Check(this, ref mark1);
8 }
9 }
10
11 //这是CodeAccessSecurityEngine 的Check方法
12
13 internal virtual void Check(CodeAccessPermission cap, ref StackCrawlMark stackMark)
14 {
15 if (!this.PreCheck(cap, null, 1, ref stackMark, PermissionType.DefaultFlag))
16 {
17 this.Check(PermissionToken.GetToken(cap), cap, ref stackMark, -1, (cap is IUnrestrictedPermission) ? 1 : 0);
18 }
19 }
20
21
(只针对CodeAccessSecurity),首先他有个跟代码栈有关的权限列表,程序栈最下面应该有个Fulltrust的权限,到了栈[FileIOPermission(SecurityAction.Deny,Read=@"d:\")]这里时权限就只有Fulltrust 去掉 FileIOPermission(FileIOPermissionAccess.Read,"d:\") 的权限。调起demand命令时,发现并无 FileIOPermission(FileIOPermissionAccess.Read,"d:\")权限,抛出异常。