C#强化系列文章九:代码访问安全性使用

在.Net Framework中提供了代码访问安全性(Code Access Security),它的主要作用就是限制代码的使用权限。可以控制各种系统资源的访问权限、可以要求代码的调用方拥有特定的权限......。比如我们可以控制自己的dll只能在什么条件下由什么人调用,特别是在Asp.net中可以限制不同代码的安全权限,从源头限制住网络上的攻击等。

本文的主要内容如下:

1、在Asp.Net中使用自定义的信任级别

2、配置Sqlconnection的代码访问权限

3、实现和使用一个最简版的自定义权限

 

在Asp.Net中使用自定义的信任级别

Asp.Net默认在C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config中配置了网站的信任级别: 
C#强化系列文章九:代码访问安全性使用
C#强化系列文章九:代码访问安全性使用      <securityPolicy>
C#强化系列文章九:代码访问安全性使用        
<trustLevel name="Full" policyFile="internal"/>
C#强化系列文章九:代码访问安全性使用        
<trustLevel name="High" policyFile="web_hightrust.config"/>
C#强化系列文章九:代码访问安全性使用        
<trustLevel name="Medium" policyFile="web_mediumtrust.config"/>
C#强化系列文章九:代码访问安全性使用        
<trustLevel name="Low" policyFile="web_lowtrust.config"/>
C#强化系列文章九:代码访问安全性使用        
<trustLevel name="Minimal" policyFile="web_minimaltrust.config"/>
C#强化系列文章九:代码访问安全性使用      
</securityPolicy>
C#强化系列文章九:代码访问安全性使用      
<trust level="Full" originUrl=""/>
C#强化系列文章九:代码访问安全性使用
C#强化系列文章九:代码访问安全性使用
默认为Full,表示拥有最大的权限,当然风险也就最高,我们可以在自己的网站下的web.config中自定义信任级别:
C#强化系列文章九:代码访问安全性使用        <securityPolicy>
C#强化系列文章九:代码访问安全性使用            
<trustLevel name="Custom" policyFile="E:\_NetProject\PermissionTrust\WebSite11\web_customtrust.config"/>
C#强化系列文章九:代码访问安全性使用        
</securityPolicy>
C#强化系列文章九:代码访问安全性使用        
<trust level="Custom" originUrl=""/>

这里使用了自定义的配置文件,其实也就是复制C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web_lowtrust.config文件,然后在此文件上进行适当修改就可以了(使用此配置默认是不允许连接数据库的)

 

配置Sqlconnection的代码访问权限

配置的方法就是修改自定义的web_customtrust.config文件,修改后的文件如下所示:粗体部分为修改点

C#强化系列文章九:代码访问安全性使用web_customtrust.config

加入以上的配置后限制使用SqlConnection时只能访问dbserver上的db1数据库,不能访问其他数据库,用户名密码等可以*输入,也就是在代码中只能:

C#强化系列文章九:代码访问安全性使用SqlConnection connection = new SqlConnection("data source=dbserver;User ID=gspring;Password=***;initial catalog=db1")

如果连接其他数据库就会报错:

C#强化系列文章九:代码访问安全性使用说明: 应用程序试图执行安全策略不允许的操作。要授予此应用程序所需的权限,请与系统管理员联系,或在配置文件中更改该应用程序的信任级别。 
C#强化系列文章九:代码访问安全性使用异常详细信息: System.Security.SecurityException: 请求“System.Data.SqlClient.SqlClientPermission, System.Data, Version
=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”类型的权限已失败。

这样就从源头上限制住了数据库的连接操作。

当然如果希望可以连接任意数据库,可以修改为如下配置:

C#强化系列文章九:代码访问安全性使用<IPermission class="SqlClientPermission" version="1" Unrestricted="true"/>

 

实现和使用一个最简版的自定义权限

自定义一个代码访问权限需要从CodeAccessPermission继承,并且要实现IUnrestrictedPermission接口,主要需实现的方法有:

Copy 创建当前权限对象的副本。
Intersect 返回当前类与传递的类所允许权限的交集。
IsSubsetOf 如果传递的权限包括当前权限允许的一切操作,则 IsSubsetOf 返回 true。
FromXml 对您的自定义权限的 XML 表示形式进行解码。
ToXml 对您的自定义权限的 XML 表示形式进行编码。
Union 创建一个权限,该权限是当前权限与指定权限的并集。

C#强化系列文章九:代码访问安全性使用
  1C#强化系列文章九:代码访问安全性使用using System;
  2C#强化系列文章九:代码访问安全性使用using System.Text;
  3C#强化系列文章九:代码访问安全性使用using System.Security;
  4C#强化系列文章九:代码访问安全性使用using System.Security.Permissions;
  5C#强化系列文章九:代码访问安全性使用
  6C#强化系列文章九:代码访问安全性使用namespace MyPermission
  7C#强化系列文章九:代码访问安全性使用{
  8C#强化系列文章九:代码访问安全性使用    [Serializable]
  9C#强化系列文章九:代码访问安全性使用    public sealed class CustomPermission : CodeAccessPermission, IUnrestrictedPermission
 10C#强化系列文章九:代码访问安全性使用    {
 11C#强化系列文章九:代码访问安全性使用        private DateTime _expiredDate;
 12C#强化系列文章九:代码访问安全性使用
 13C#强化系列文章九:代码访问安全性使用        public DateTime ExpiredDate
 14C#强化系列文章九:代码访问安全性使用        {
 15C#强化系列文章九:代码访问安全性使用            get return _expiredDate; }
 16C#强化系列文章九:代码访问安全性使用            set { _expiredDate = value; }
 17C#强化系列文章九:代码访问安全性使用        }

 18C#强化系列文章九:代码访问安全性使用
 19C#强化系列文章九:代码访问安全性使用        public CustomPermission()
 20C#强化系列文章九:代码访问安全性使用        {
 21C#强化系列文章九:代码访问安全性使用        }

 22C#强化系列文章九:代码访问安全性使用
 23C#强化系列文章九:代码访问安全性使用        //必须有这个方法,CAS系统会调用此方法的
 24C#强化系列文章九:代码访问安全性使用        public CustomPermission(PermissionState state)
 25C#强化系列文章九:代码访问安全性使用        {
 26C#强化系列文章九:代码访问安全性使用        }

 27C#强化系列文章九:代码访问安全性使用
 28C#强化系列文章九:代码访问安全性使用        public bool IsUnrestricted()
 29C#强化系列文章九:代码访问安全性使用        {
 30C#强化系列文章九:代码访问安全性使用            return false;
 31C#强化系列文章九:代码访问安全性使用        }

 32C#强化系列文章九:代码访问安全性使用
 33C#强化系列文章九:代码访问安全性使用        public override IPermission Copy()
 34C#强化系列文章九:代码访问安全性使用        {
 35C#强化系列文章九:代码访问安全性使用            CustomPermission copy = new CustomPermission();
 36C#强化系列文章九:代码访问安全性使用            copy.ExpiredDate = this.ExpiredDate;
 37C#强化系列文章九:代码访问安全性使用
 38C#强化系列文章九:代码访问安全性使用            return copy;
 39C#强化系列文章九:代码访问安全性使用        }

 40C#强化系列文章九:代码访问安全性使用
 41C#强化系列文章九:代码访问安全性使用        public override IPermission Intersect(IPermission target)
 42C#强化系列文章九:代码访问安全性使用        {
 43C#强化系列文章九:代码访问安全性使用            if (null == target)
 44C#强化系列文章九:代码访问安全性使用            {
 45C#强化系列文章九:代码访问安全性使用                return null;
 46C#强化系列文章九:代码访问安全性使用            }

 47C#强化系列文章九:代码访问安全性使用            else
 48C#强化系列文章九:代码访问安全性使用            {
 49C#强化系列文章九:代码访问安全性使用                return target;
 50C#强化系列文章九:代码访问安全性使用            }

 51C#强化系列文章九:代码访问安全性使用        }

 52C#强化系列文章九:代码访问安全性使用
 53C#强化系列文章九:代码访问安全性使用        private bool CheckDate(DateTime date)
 54C#强化系列文章九:代码访问安全性使用        {
 55C#强化系列文章九:代码访问安全性使用            if (System.DateTime.Now.CompareTo(date) < 0)
 56C#强化系列文章九:代码访问安全性使用            {
 57C#强化系列文章九:代码访问安全性使用                return true;
 58C#强化系列文章九:代码访问安全性使用            }

 59C#强化系列文章九:代码访问安全性使用            else
 60C#强化系列文章九:代码访问安全性使用            {
 61C#强化系列文章九:代码访问安全性使用                return false;
 62C#强化系列文章九:代码访问安全性使用            }

 63C#强化系列文章九:代码访问安全性使用        }

 64C#强化系列文章九:代码访问安全性使用
 65C#强化系列文章九:代码访问安全性使用        /// <summary>
 66C#强化系列文章九:代码访问安全性使用        /// 进行权限判断
 67C#强化系列文章九:代码访问安全性使用        /// </summary>
 68C#强化系列文章九:代码访问安全性使用        /// <param name="target"></param>
 69C#强化系列文章九:代码访问安全性使用        /// <returns></returns>

 70C#强化系列文章九:代码访问安全性使用        public override bool IsSubsetOf(IPermission target)
 71C#强化系列文章九:代码访问安全性使用        {
 72C#强化系列文章九:代码访问安全性使用            if (null == target)
 73C#强化系列文章九:代码访问安全性使用            {
 74C#强化系列文章九:代码访问安全性使用                return false//为false时,指示条件不满足,需要读取config中配置来判断
 75C#强化系列文章九:代码访问安全性使用            }

 76C#强化系列文章九:代码访问安全性使用            try
 77C#强化系列文章九:代码访问安全性使用            {
 78C#强化系列文章九:代码访问安全性使用                CustomPermission passedpermission = (CustomPermission)target;
 79C#强化系列文章九:代码访问安全性使用
 80C#强化系列文章九:代码访问安全性使用                return CheckDate(passedpermission.ExpiredDate);
 81C#强化系列文章九:代码访问安全性使用            }

 82C#强化系列文章九:代码访问安全性使用            catch (InvalidCastException)
 83C#强化系列文章九:代码访问安全性使用            {
 84C#强化系列文章九:代码访问安全性使用                throw new ArgumentException("Argument_WrongType"this.GetType().FullName);
 85C#强化系列文章九:代码访问安全性使用            }

 86C#强化系列文章九:代码访问安全性使用        }

 87C#强化系列文章九:代码访问安全性使用
 88C#强化系列文章九:代码访问安全性使用        public override void FromXml(SecurityElement PassedElement)
 89C#强化系列文章九:代码访问安全性使用        {
 90C#强化系列文章九:代码访问安全性使用            string element = PassedElement.Attribute("expireddate");
 91C#强化系列文章九:代码访问安全性使用
 92C#强化系列文章九:代码访问安全性使用            if (null != element)
 93C#强化系列文章九:代码访问安全性使用            {
 94C#强化系列文章九:代码访问安全性使用                this.ExpiredDate = Convert.ToDateTime(element);
 95C#强化系列文章九:代码访问安全性使用            }

 96C#强化系列文章九:代码访问安全性使用        }

 97C#强化系列文章九:代码访问安全性使用
 98C#强化系列文章九:代码访问安全性使用        public override SecurityElement ToXml()
 99C#强化系列文章九:代码访问安全性使用        {
100C#强化系列文章九:代码访问安全性使用            SecurityElement element = new SecurityElement("IPermission");
101C#强化系列文章九:代码访问安全性使用            Type type = this.GetType();
102C#强化系列文章九:代码访问安全性使用            StringBuilder AssemblyName = new StringBuilder(type.Assembly.ToString());
103C#强化系列文章九:代码访问安全性使用            AssemblyName.Replace('\"''\'');
104C#强化系列文章九:代码访问安全性使用            element.AddAttribute("class", type.FullName + "" + AssemblyName);
105C#强化系列文章九:代码访问安全性使用            element.AddAttribute("version""1");
106C#强化系列文章九:代码访问安全性使用            element.AddAttribute("expireddate"this.ExpiredDate.ToString());
107C#强化系列文章九:代码访问安全性使用            return element;
108C#强化系列文章九:代码访问安全性使用        }

109C#强化系列文章九:代码访问安全性使用    }

110C#强化系列文章九:代码访问安全性使用}
C#强化系列文章九:代码访问安全性使用

 例子比较简单,就是读取配置中的过期时间进行判断,需要特别说明的地方有:

1、public CustomPermission(PermissionState state)这个构造函数必须要有,CAS内部会调用此方法

2、将程序集添加到受信任的程序集列表中,因为自定义权限将参与 .NET Framework 安全系统,所以它必须完全受信任。依次执行以下命令:

caspol -rf MyPermission.dll    --从策略级别移除完全信任程序集
gacutil -i MyPermission.dll     --注册GAC
caspol -af MyPermission.dll   --将完全信任程序集添加到策略级别

3、在将程序集加入GAC之后,会默认从GAC中读取dll信息,不会读取当前项目下新生成的dll,需要从GAC中把此DLL删除后才可以。ps:我当时在CustomPermission里面加入一个新的方法,结果在自己的网站下一直找不到,把GAC中的信息删除之后才能找到,不知道算不算VS2005的一个Bug

4、在MyPermission程序集的AssemblyInfo.cs文件中添加配置:

 

C#强化系列文章九:代码访问安全性使用[assembly: AllowPartiallyTrustedCallers]

 要不然会报粗:该程序集不支持部分受信任的调用方

5、在web_customtrust.config文件中加入配置

    a、在SecurityClasses节点加入:

C#强化系列文章九:代码访问安全性使用            <SecurityClass Name="MyPermission" Description="MyPermission.CustomPermission, MyPermission, Version=1.0.0.0, Culture=neutral, PublicKeyToken=97b2744b86090fe0"/>

    b、在Name="ASP.Net"的PermissionSet节点加入:

C#强化系列文章九:代码访问安全性使用<IPermission class="MyPermission" version="1" expireddate="2008-07-22"/>

 

配置好之后就可以在代码中应有此安全策略了

C#强化系列文章九:代码访问安全性使用

C#强化系列文章九:代码访问安全性使用    private void Test()
C#强化系列文章九:代码访问安全性使用    
{
C#强化系列文章九:代码访问安全性使用        CustomPermission Perm 
= new CustomPermission();
C#强化系列文章九:代码访问安全性使用        Perm.Demand();

          .......

          .......
C#强化系列文章九:代码访问安全性使用    }

C#强化系列文章九:代码访问安全性使用

这个是应用安全策略的一种方式,另外一种方式是使用声明式安全性,需要再定义一个属性类来支持,这里就不再详述了。

 

小结:总之代码访问安全性可以有效的限制代码的使用权限,本文的例子只是用来演示使用方法,实际应用会比这个复杂的多。比如在Sharepoint中可能允许客户上传自己的dll代码,客户的代码有可能调用系统资源和我们提供的共通代码,那么我们就可以通过代码访问安全性来限制客户代码可以访问哪些资源,可以调用哪些共通dll等。


    本文转自永春博客园博客,原文链接:http://www.cnblogs.com/firstyi/archive/2008/07/24/1250447.html,如需转载请自行联系原作者



上一篇:Unity TIP4: 带泛型参数的接口注入(interface,generic)


下一篇:Hibernate一对多(多对一)外键设置汇总