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中配置了网站的信任级别: 

       < securityPolicy >
        
< trustLevel  name ="Full"  policyFile ="internal" />
        
< trustLevel  name ="High"  policyFile ="web_hightrust.config" />
        
< trustLevel  name ="Medium"  policyFile ="web_mediumtrust.config" />
        
< trustLevel  name ="Low"  policyFile ="web_lowtrust.config" />
        
< trustLevel  name ="Minimal"  policyFile ="web_minimaltrust.config" />
      
</ securityPolicy >
      
< trust  level ="Full"  originUrl ="" />

默认为Full,表示拥有最大的权限,当然风险也就最高,我们可以在自己的网站下的web.config中自定义信任级别:

         < securityPolicy >
            
< trustLevel  name ="Custom"  policyFile ="E:/_NetProject/PermissionTrust/WebSite11/web_customtrust.config" />
        
</ securityPolicy >
        
< trust  level ="Custom"  originUrl ="" />

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

 

配置Sqlconnection的代码访问权限

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


< configuration >
  
< mscorlib >
    
< security >
      
< policy >
        
< PolicyLevel  version ="1" >
          
< SecurityClasses >
            
< SecurityClass  Name ="AllMembershipCondition"  Description ="System.Security.Policy.AllMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="AspNetHostingPermission"  Description ="System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="FileIOPermission"  Description ="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="FirstMatchCodeGroup"  Description ="System.Security.Policy.FirstMatchCodeGroup, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="IsolatedStorageFilePermission"  Description ="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="NamedPermissionSet"  Description ="System.Security.NamedPermissionSet" />
            
< SecurityClass  Name ="SecurityPermission"  Description ="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="StrongNameMembershipCondition"  Description ="System.Security.Policy.StrongNameMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="UnionCodeGroup"  Description ="System.Security.Policy.UnionCodeGroup, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="UrlMembershipCondition"  Description ="System.Security.Policy.UrlMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="ZoneMembershipCondition"  Description ="System.Security.Policy.ZoneMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            
< SecurityClass  Name ="SqlClientPermission"  Description ="System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
          
</ SecurityClasses >
          
< NamedPermissionSets >
            
< PermissionSet
                    
class ="NamedPermissionSet"
                    version
="1"
                    Unrestricted
="true"
                    Name
="FullTrust"
                    Description
="Allows full access to all resources"
                        
/>
            
< PermissionSet
                    
class ="NamedPermissionSet"
                    version
="1"
                    Name
="Nothing"
                    Description
="Denies all resources, including the right to execute"
                        
/>
            
< PermissionSet
                    
class ="NamedPermissionSet"
                    version
="1"
                    Name
="ASP.Net" >

              
< IPermission
                      
class ="AspNetHostingPermission"
                      version
="1"
                      Level
="High"   
                      
/>
              
< IPermission
                      
class ="FileIOPermission"
                      version
="1"
                      Read
="$AppDir$"
                      PathDiscovery
="$AppDir$"
                            
/>
              
< IPermission
                      
class ="IsolatedStorageFilePermission"
                      version
="1"
                      Allowed
="AssemblyIsolationByUser"
                      UserQuota
="1048576"
                            
/>
              
< IPermission
                      
class ="SecurityPermission"
                      version
="1"
                      Flags
="Execution"
                            
/>
              
< IPermission  class ="SqlClientPermission"  version ="1" >
                
< add  ConnectionString ="data source=dbserver;initial catalog=db1"
                     KeyRestrictions
="User ID=;Password=;Connection Reset="
                  KeyRestrictionBehavior
="AllowOnly" />
              
</ IPermission >
          
</ NamedPermissionSets >
          
< CodeGroup
                  
class ="FirstMatchCodeGroup"
                  version
="1"
                  PermissionSetName
="Nothing" >
            
< IMembershipCondition
                    
class ="AllMembershipCondition"
                    version
="1"
                        
/>
            
< CodeGroup
                    
class ="UnionCodeGroup"
                    version
="1"
                    PermissionSetName
="ASP.Net" >
              
< IMembershipCondition
                      
class ="UrlMembershipCondition"
                      version
="1"
                      Url
="$AppDirUrl$/*"
                            
/>
            
</ CodeGroup >
            
< CodeGroup
                    
class ="UnionCodeGroup"
                    version
="1"
                    PermissionSetName
="ASP.Net" >
              
< IMembershipCondition
                      
class ="UrlMembershipCondition"
                      version
="1"
                      Url
="$CodeGen$/*"
                            
/>
            
</ CodeGroup >
            
< CodeGroup  class ="UnionCodeGroup"  version ="1"  PermissionSetName ="Nothing" >
              
< IMembershipCondition
                    
class ="ZoneMembershipCondition"
                    version
="1"
                    Zone
="MyComputer"   />
              
< CodeGroup
                      
class ="UnionCodeGroup"
                      version
="1"
                      PermissionSetName
="FullTrust"
                      Name
="Microsoft_Strong_Name"
                      Description
="This code group grants code signed with the Microsoft strong name full trust. " >
                
< IMembershipCondition
                        
class ="StrongNameMembershipCondition"
                        version
="1"
                        PublicKeyBlob
="002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293"
                                
/>
              
</ CodeGroup >
              
< CodeGroup
                      
class ="UnionCodeGroup"
                      version
="1"
                      PermissionSetName
="FullTrust"
                      Name
="Ecma_Strong_Name"
                      Description
="This code group grants code signed with the ECMA strong name full trust. " >
                
< IMembershipCondition
                        
class ="StrongNameMembershipCondition"
                        version
="1"
                        PublicKeyBlob
="00000000000000000400000000000000"
                                
/>
              
</ CodeGroup >
            
</ CodeGroup >
          
</ CodeGroup >
        
</ PolicyLevel >
      
</ policy >
    
</ security >
  
</ mscorlib >
</ configuration >

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

SqlConnection connection  =   new  SqlConnection( " data source=dbserver;User ID=gspring;Password=***;initial catalog=db1 " )

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

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

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

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

< IPermission  class ="SqlClientPermission"  version ="1"  Unrestricted ="true" />

 

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

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

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

  1 using  System;
  2 using  System.Text;
  3 using  System.Security;
  4 using  System.Security.Permissions;
  5
  6 namespace  MyPermission
  7 {
  8     [Serializable]
  9      public   sealed   class  CustomPermission : CodeAccessPermission, IUnrestrictedPermission
 10      {
 11          private  DateTime _expiredDate;
 12
 13          public  DateTime ExpiredDate
 14          {
 15              get   return  _expiredDate; }
 16              set   { _expiredDate  =  value; }
 17         }

 18
 19          public  CustomPermission()
 20          {
 21         }

 22
 23          // 必须有这个方法,CAS系统会调用此方法的
 24          public  CustomPermission(PermissionState state)
 25          {
 26         }

 27
 28          public   bool  IsUnrestricted()
 29          {
 30              return   false ;
 31         }

 32
 33          public   override  IPermission Copy()
 34          {
 35             CustomPermission copy  =   new  CustomPermission();
 36             copy.ExpiredDate  =   this .ExpiredDate;
 37
 38              return  copy;
 39         }

 40
 41          public   override  IPermission Intersect(IPermission target)
 42          {
 43              if  ( null   ==  target)
 44              {
 45                  return   null ;
 46             }

 47              else
 48              {
 49                  return  target;
 50             }

 51         }

 52
 53          private   bool  CheckDate(DateTime date)
 54          {
 55              if  (System.DateTime.Now.CompareTo(date)  <   0 )
 56              {
 57                  return   true ;
 58             }

 59              else
 60              {
 61                  return   false ;
 62             }

 63         }

 64
 65          ///   <summary>
 66          ///  进行权限判断
 67          ///   </summary>
 68          ///   <param name="target"></param>
 69          ///   <returns></returns>

 70          public   override   bool  IsSubsetOf(IPermission target)
 71          {
 72              if  ( null   ==  target)
 73              {
 74                  return   false // 为false时,指示条件不满足,需要读取config中配置来判断
 75             }

 76              try
 77              {
 78                 CustomPermission passedpermission  =  (CustomPermission)target;
 79
 80                  return  CheckDate(passedpermission.ExpiredDate);
 81             }

 82              catch  (InvalidCastException)
 83              {
 84                  throw   new  ArgumentException( " Argument_WrongType " this .GetType().FullName);
 85             }

 86         }

 87
 88          public   override   void  FromXml(SecurityElement PassedElement)
 89          {
 90              string  element  =  PassedElement.Attribute( " expireddate " );
 91
 92              if  ( null   !=  element)
 93              {
 94                  this .ExpiredDate  =  Convert.ToDateTime(element);
 95             }

 96         }

 97
 98          public   override  SecurityElement ToXml()
 99          {
100             SecurityElement element  =   new  SecurityElement( " IPermission " );
101             Type type  =   this .GetType();
102             StringBuilder AssemblyName  =   new  StringBuilder(type.Assembly.ToString());
103             AssemblyName.Replace( ' /" ' ' / '' );
104             element.AddAttribute( " class " , type.FullName  +   " "   +  AssemblyName);
105             element.AddAttribute( " version " " 1 " );
106             element.AddAttribute( " expireddate " this .ExpiredDate.ToString());
107              return  element;
108         }

109     }

110 }

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

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文件中添加配置:

 

[assembly: AllowPartiallyTrustedCallers]

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

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

    a、在SecurityClasses节点加入:

             < SecurityClass  Name ="MyPermission"  Description ="MyPermission.CustomPermission, MyPermission, Version=1.0.0.0, Culture=neutral, PublicKeyToken=97b2744b86090fe0" />

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

< IPermission  class ="MyPermission"  version ="1"  expireddate ="2008-07-22" />

 

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

     private   void  Test()
    
{
        CustomPermission Perm 
=   new  CustomPermission();
        Perm.Demand();

          .......

          .......
    }

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

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值