我做了一个示例应用程序来试图解决这个问题.
通话方式:
[FileIOPermission(SecurityAction.Deny,ViewAndModify = @"C:\")] static void Main(string[] args) { WriteTest testWriter = new WriteTest(); testWriter.Test(); Console.Read(); }
在一个单独的类库中,我有:
public class WriteTest { public void Test() { try { FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.Write,@"C:\"); permission.Assert(); using (StreamWriter sw = new StreamWriter(@"C:\test.txt")) { sw.WriteLine("testing!"); sw.Flush(); } Console.WriteLine("Writen to file!"); } catch (SecurityException sec) { Console.WriteLine("No privileges!"); } } }
这段代码执行得很好.它将写入文件.我的问题是这究竟是如何工作的?如果我只是断言我想要的权限以便它跳过检查,这不会使安全类失效吗?如果我将Assert更改为Demand它会引发异常.
安全类的重点是不允许我设置权限,这样当我调用第三方类时,我可以防止它变成流氓并做一些我不希望它做的事情?我知道如果我在AppDomain中加载dll,即使第三方DLL确实使用Assert,我也会得到这种效果,如果我直接调用它就会起作用,这似乎很奇怪.我试过在Assert上阅读MSDN文档,但我发现很难理解.
解决方法
例如,假设部分信任的Silverlight应用程序想要使用System.Net.WebRequest类发出HTTP请求.建立网络连接需要SocketPermission,但这是一个功能强大的低级别权限,不应授予来自Internet的不受信任的代码.因此,WebRequest需要一个不太强大的权限WebPermission,然后在继续建立网络连接之前断言SocketPermission.
现在,在您的特定示例中,Assert()会覆盖Deny,因为类库在与应用程序相同的权限级别运行 – 应用程序和类库都可能作为完全信任运行.程序集始终可以在其授权集中Assert()任何权限.要在类库上强制执行Deny,您必须将类库放在沙箱中.
注意:在.NET 4.0中,Deny已被弃用.从MSDN Library开始:
Runtime support has been removed for enforcing the Deny,RequestMinimum,RequestOptional,and RequestRefuse permission requests. In general,these requests were not well understood and presented the potential for security vulnerabilities when they were not used properly:
- A Deny action could be easily overridden by an Assert action. The code in an assembly was able to execute an Assert action for a permission if the permission was in the grant set for the assembly. The Assert prevented the Deny from being seen on the stack,making it ineffective.