前面好几篇文章,老周都跟大伙伴们聊了跟应用程序域有关的话题,干脆咱们一聊到底吧,做学问就应该这样,有恒心。

App Domain的创建新应用程序域的方法中,有一个特殊的重载:

public static AppDomain CreateDomain(string friendlyName, Evidence securityInfo, AppDomainSetup info, PermissionSet grantSet, params StrongName[] fullTrustAssemblies);

这个重载比较特殊,它与咱们今天扯的话题接近,因为它的参数列表中有一个是 PermissionSet 类型的,它表示一个权限的集合,当创建应用程序域时,通过这个权限集合,限制在新应用程序域中执行的代码的权限。在各个CreateDomain方法的重载中,只有这个有设置权限集的参数。

运用这个重载方法,可以将你觉得要限制权限的代码放到这个新的应用程序域中执行,即创建一个“沙箱”。比如,你拿到别人写的一个类库A,不过你不知道这个类库A在执行过程中会干什么,于是,你希望在使用这个来路不明的类库时,可以限制一下它,例如不让它读写文件,或者说只允许它访问某些目录和文件。

为了偷工减料,写出豆腐渣程序,老周举的这个例子,是把做测试用的代码写到主程序集中。它有一个类,类中有一个方法,调用之后,会在“文档”库中创建一个文件,然后写入一些见不得人的内容。

    public class Demo : MarshalByRefObject
{
public void WirteFile()
{
string myDoc = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string filePath = Path.Combine(myDoc, Guid.NewGuid() + ".txt");
using (FileStream fs = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read))
{
byte[] data = Encoding.UTF8.GetBytes("卖假药啦。");
fs.Write(data, , data.Length);
}
}
}

然后,创建一个新的应用程序域,再在新域里面执行刚刚写好的类。之所以继承MarshalByRefObject类,是希望可以跨应用程序域调用,并且是按引用传递。

调用如下:

            // 添加程序集凭据
// 此处是为了装逼,才写以下几行
// 其实你可以直接用 AppDomain.CurrentDomain.Evidence
Evidence evd = new Evidence();
Assembly currAss = Assembly.GetExecutingAssembly();
Hash hsevd = new Hash(currAss);
evd.AddAssemblyEvidence<Hash>(hsevd); // 准备相关信息
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; // 准备权限
PermissionSet ps = new PermissionSet(PermissionState.None);
// Execution 权限必须,不然连代码都不能执行了
SecurityPermission secps = new SecurityPermission(SecurityPermissionFlag.Execution);
ps.AddPermission(secps); // 创建新域
AppDomain newAppdm = AppDomain.CreateDomain("good", evd, setup, ps);
// 创建测试对象实例
Demo d = (Demo)newAppdm.CreateInstanceAndUnwrap(currAss.FullName, $"{nameof(TestApp)}.{nameof(Demo)}");
d.WriteFile(); d = null;
AppDomain.Unload(newAppdm);

Evidence这东西比较抽象,你可以理解为程序集用来证明它是合法身份的一些信息,比如这里,我用当前程序集的 Hash 值来做为证明,因为这个 Demo 类是写在当前程序集中的(刚刚说了,为了偷工减料)。

注意权限集合是 PermissionSet 类,它是个容器,你可以根据需要,向里面添加权限声明。在上面代码中,我加了一个最基本的安全权限——SecurityPermission,这个你得加,因为它是最最最基本的权限,如果不加,连代码都执行不了,那就等于这段代码是废的,用 SecurityPermissionFlag 枚举来描述代码应具有的基础权限,这些值可以组合使用,Execution表示允许执行代码,如果你连这个权限也不给,干脆把 Demo 类开除算了。

顺便说一下,在new出PermissionSet 实例时,构造函数会要求一个 PermissionState值,你应该把它设置为 None,这样权限才会对代码进行限制,如果用了Unrestricted ,表示不做限制。

调用 CreateInstanceAndUnwrap 方法时,是在新的应用程序域中创建 Demo 实例,但可以通过引用,把实例封送到当前应用程序域中,这样可以跨域调用,实际上 WriteFile 方法是在新的应用程序域中执行的。

如果你要允许代码访问文件和目录,你必须加上FileIOPermission权限,但这里我没加,看看运行后会如何。

因为我不给它权限,所以它没办法写入文件了。

现在我们来改一下代码,在创建应用程序域前,向权限集合添加 FileIOPermission 权限。

            string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
FileIOPermission fps = new FileIOPermission(FileIOPermissionAccess.AllAccess, docPath);
ps.AddPermission(fps);

再执行一下,如果执行成功,会发现“文档”库里面多了一个文件。

好了,今天就扯到这里了。

示例代码下载地址

【.net 深呼吸】限制执行代码的权限的更多相关文章

  1. sqlserver授予用户查看执行计划的权限

    sqlserver查看语句的执行计划是非常重要的,可以提高开发人员代码的质量.所以有必要授予开发人员对数据库查看执行计划的权限.   查看执行计划的权限属于数据库一级别的权限,具体例子如下   use ...

  2. Node.js 反序列化漏洞远程执行代码(CVE-2017-5941)

    2.1 摘要 2.1.1 漏洞介绍 漏洞名称: Exploiting Node.js deserialization bug for Remote Code Execution 漏洞CVE id: C ...

  3. 可执行代码(Executable Code)目标代码(object code)

    小结: 1.可执行代码(Executable Code)是指将目标代码(object code)连接后形成的代码,简单来说是机器能够直接执行的代码. https://baike.baidu.com/i ...

  4. Windows Shell远程执行代码漏洞((CVE-2018-8414)复现

    0x00   SettingContent-ms文件介绍 .SettingContent-ms是在Windows 10中引入的一种文件类型,它的内容是XML格式进行编写的,主要用于创建Windows设 ...

  5. Jenkins Java 反序列化远程执行代码漏洞(CVE-2017-1000353)

    Jenkins Java 反序列化远程执行代码漏洞(CVE-2017-1000353) 一.漏洞描述 该漏洞存在于使用HTTP协议的双向通信通道的具体实现代码中,jenkins利用此通道来接收命令,恶 ...

  6. 【转】C# 将字符串或表达式直接转为可执行代码的办法

    C# 将字符串或表达式直接转为可执行代码的办法 反射类 using System; using System.Data; using System.Configuration; using Syste ...

  7. [转载]基于TFS实践敏捷-修复Bug和执行代码评审

    本主题阐释了这些功能,以继续这一关注虚拟敏捷团队成员的一天的教程. Peter 忙于编写一些代码以完成积压工作 (backlog) 项任务.但是,他的同事发现了一个阻碍他们工作的 Bug,他想立即修复 ...

  8. 在VC环境下执行代码出现错误

    这是在执行代码过程中出现的错误,源代码在别的电脑上能运行,在自己的VC里运行就出现错误,在网上也搜过解决办法,但还是有点不太理解,是编程环境的问题h还是代码本身也存在问题???

  9. C#实现每隔一段时间执行代码(多线程)

    总结以下三种方法,实现c#每隔一段时间执行代码: 方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间: 方法二:使用System.Timers.Timer类: 方法三:使用Sys ...

随机推荐

  1. 我为什么要写LeetCode的博客?

    # 增强学习成果 有一个研究成果,在学习中传授他人知识和讨论是最高效的做法,而看书则是最低效的做法(具体研究成果没找到地址).我写LeetCode博客主要目的是增强学习成果.当然,我也想出名,然而不知 ...

  2. JavaScript中Math对象的方法介绍

    1.比较最值方法 比较最值有两种方法,max() 和 min() 方法. 1.1 max() 方法,比较一组数值中的最大值,返回最大值. var maxnum = Math.max(12,6,43,5 ...

  3. HTML中上传与读取图片或文件(input file)----在路上(25)

    input file相关知识简例 在此介绍的input file相关知识为: 上传照片及文件,其中包括单次上传.批量上传.删除照片.增加照片.读取图片.对上传的图片或文件的判断,比如限制图片的张数.限 ...

  4. 23种设计模式--观察者模式-Observer Pattern

    一.观察者模式的介绍      观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...

  5. Oracle安装部署,版本升级,应用补丁快速参考

    一.Oracle安装部署 1.1 单机环境 1.2 Oracle RAC环境 1.3 Oracle DataGuard环境 1.4 主机双机 1.5 客户端部署 二.Oracle版本升级 2.1 单机 ...

  6. CSS 3 学习——渐变

    通过CSS渐变创建的是一个没有固定比例和固定尺寸的<image>类型,也就是说是一张图片,这张图片的尺寸由所应用的元素的相关信息决定.凡是支持图片类型的CSS属性都可以设置渐变,而支持颜色 ...

  7. C++ 11 多线程--线程管理

    说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...

  8. 神技!微信小程序(应用号)抢先入门教程(附最新案例DEMO-豆瓣电影)持续更新

    微信小程序 Demo(豆瓣电影) 由于时间的关系,没有办法写一个完整的说明,后续配合一些视频资料,请持续关注 官方文档:https://mp.weixin.qq.com/debug/wxadoc/de ...

  9. 2Sum

    用哈希表(unordered_map)使得时间复杂度从O(n*n)降到O(n),空间复杂度从O(1)增到O(n):一边找一边插入哈希表 注意 在C++11以前要使用unordered_map需要 #i ...

  10. php 基础代码大全(不断完善中)

    下面是基础的PHP的代码,不断完善中~ //语法错误(syntax error)在语法分析阶段,源代码并未被执行,故不会有任何输出. /* [命名规则] */ 常量名 类常量建议全大写,单词间用下划线 ...