.NET: 通过AppDomain级别控制安全策略的例子
来源:互联网 发布:react.js中文网 编辑:程序博客网 时间:2024/06/05 08:11
这是在课堂上讲的一个小范例。场景是:
1. 我们有一个主程序,它公开了一套API,允许其他开发人员为它设计插件
2. 因为插件不是我们设计的,所以我们需要确保这些插件不会恶意地伤害到用意。为此,我们希望将插件的运行权限降低。
解决方案就是,我们单独用一个AppDomain来运行这些插件,并且在该AppDomain级别单独设置安全策略。
1. API
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace API{ public interface IPlugin { void Run(); }}
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
2. Plugin
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace PluginSample{ public class Plug:API.IPlugin { #region IPlugin 成员 void API.IPlugin.Run() { MainForm form = new MainForm(); form.ShowDialog(); } #endregion }}
Plugin中有一个窗体,里面有一个按钮,执行访问注册表的操作
using System;using System.Windows.Forms;using Microsoft.Win32;namespace PluginSample{ public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { RegistryKey key = Registry.CurrentUser.CreateSubKey("Plugins"); key.SetValue("Version", "1.0.0"); key.SetValue("Update", DateTime.Now.ToString()); MessageBox.Show("操作已经完成"); } }}
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
3. 宿主程序
为了实现跨应用程序域的加载,我们设计了一个AssemblyLoader类型
using System;using System.Linq;using System.Reflection;namespace Host_WinForms{ [Serializable] class AssemblyLoader:MarshalByRefObject //必须继承MarshalByRefObject,否则无法实现AppDomain级别的安全控制 { public string[] GetPluginTypeNames(string path) { Assembly ass = Assembly.LoadFile(path); var query = from type in ass.GetTypes() where type.GetInterface(typeof(API.IPlugin).FullName) != null select type.FullName; return query.ToArray(); } public void RunPlugin(string path, string typeName) { Assembly ass = Assembly.LoadFile(path); API.IPlugin plugin = (API.IPlugin)ass.CreateInstance(typeName); plugin.Run(); } }}.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
宿主程序有一个MainForm
using System;using System.Windows.Forms;using System.IO;using System.Security.Permissions;using System.Security.Policy;using System.Security;namespace Host_WinForms{ public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private void Log(string message) { richTextBox1.AppendText(DateTime.Now.ToString().PadRight(25)); richTextBox1.AppendText(message); richTextBox1.AppendText(Environment.NewLine); } private void MainForm_Load(object sender, EventArgs e) { Log("主程序启动"); Log("主程序域中的程序集:"); foreach (var item in AppDomain.CurrentDomain.GetAssemblies()) { Log(item.FullName); } //加载所有的插件(遍历当前目录下面的dll),动态创建菜单项目 AppDomain plugindomain = AppDomain.CreateDomain("PluginDomain"); AssemblyLoader loader = (AssemblyLoader)plugindomain.CreateInstanceFromAndUnwrap("Host_WinForms.exe", typeof(AssemblyLoader).FullName); foreach (var item in Directory.GetFiles(Environment.CurrentDirectory, "*.dll")) { foreach (var type in loader.GetPluginTypeNames(item)) { ToolStripMenuItem menuitem = new ToolStripMenuItem(type); menuitem.Tag = item; menuitem.Click += (o1, e1) => { //当点击了之后执行有关的插件 AppDomain plugindomaintemp = AppDomain.CreateDomain("PluginDomain"); PolicyLevel level = PolicyLevel.CreateAppDomainLevel(); PermissionSet ps = level.GetNamedPermissionSet("Internet"); ps.AddPermission(new FileIOPermission( FileIOPermissionAccess.AllAccess, Environment.CurrentDirectory)); level.RootCodeGroup.PolicyStatement = new PolicyStatement(ps); plugindomaintemp.SetAppDomainPolicy(level); try { AssemblyLoader loadertemp = (AssemblyLoader)plugindomaintemp.CreateInstanceFromAndUnwrap( "Host_WinForms.exe", typeof(AssemblyLoader).FullName); ToolStripMenuItem temp = (ToolStripMenuItem)o1; loadertemp.RunPlugin(temp.Tag.ToString(), temp.Text); } catch (Exception ex) { MessageBox.Show(string.Format("运行插件发生如下错误:{0}", ex.Message)); } finally { AppDomain.Unload(plugindomaintemp); } }; AllPluginMenu.DropDownItems.Add(menuitem); } } AppDomain.Unload(plugindomain); Log("主程序域中的程序集:"); foreach (var item in AppDomain.CurrentDomain.GetAssemblies()) { Log(item.FullName); } } }}.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
4. 运行效果
- .NET: 通过AppDomain级别控制安全策略的例子
- Net下的AppDomain编程
- .Net下的AppDomain编程
- 通过例子理解mysql的事务隔离级别
- 通过例子理解事务的4种隔离级别
- 浅析.Net下的AppDomain编程
- 浅析.Net下的AppDomain编程
- 浅析.Net下的AppDomain编程
- 浅析.Net下的AppDomain编程
- 浅析.Net下的AppDomain编程
- 浅析.Net下的AppDomain编程
- 浅析.Net下的AppDomain编程
- 浅析.Net下的AppDomain编程
- 浅析.Net下的AppDomain编程
- 通过windows注册表的修改来控制uac的级别
- .NET: 如何通过AppDomain动态加载插件程序
- 通过 AppDomain 的 ShadowCopying 功能实现 Assembly 的动态替换
- 事务的级别控制
- .NET : 一定不要忘记关闭DataReader对象
- .NET : 如何利用GDI+绘制折线图
- .NET: 如何通过AppDomain动态加载插件程序
- 任务栏音量图标消失不见之解决方法汇总
- 。NET :遍历某个权限集中的权限列表
- .NET: 通过AppDomain级别控制安全策略的例子
- DataTable转换成JSON字符串的函数
- .NET : 如何在Windows Service中获取到当前工作目录
- Silverlight学习资源
- ASP.NET: 在Win 7中安装PetShop范例时要注意的问题
- .NET Mail : 注意Win 7 不再包含SMTP服务
- ASP.NET : Win7 及 IIS 7中对于处理程序映射
- csdn,I'm back
- Win7 : 如何修改某种文件的默认打开方式