扩展.net安全机制

原创 2004年06月24日 10:00:00

.net安全机制涉及很多方面,这里只讲基本的基于角色的安全机制。.net提供了PrincipalPermission类,PrincipalPermissionAttribute类以及IPrincipal派生类支持基于角色的安全控制。内建的支持使用很方便,但灵活性却不高。举个例子吧:

     class SomeClass

     {

         [PrincipalPermission(SecurityAction.Demand, Role="admin"]

         public void SomeMethod()

         {

         }

     }

上面的代码表明只有拥有admin角色的用户才能访问SomeMethod方法,上面采用了声名式的方式,也是最方便的,当然也可以在代码中显示调用Demand检查权限或者调用IsInRoll更灵活的控制。在运行时,CLR会自动检查当前用户的Principal,检查admin是否是Principal的一个角色,关于如何为Principal对象设置角色,这里就略去了。
这样的方式虽然简单,却往往不能直接使用,因为在实际的项目中,我们往往不能在编码时确定特定角色所能执行的功能。也就是说,我们需要在运行时改变一个角色所能访问的功能。这时候,使用PrincipalPermission属性就不能解决问题了,.net似乎没有提供这样的解决方案,幸运的是,.net确实提供了扩展机制,使我们可以编写自己的权限控制机制。
为了实现上述可在运行时修改权限的机制,我们的目标是编写一个类似于PrincipalPermission的属性,让我们可以这样写:

[CustomSecurity(SecurityAction.Demand, FuncID=Func1]

public void SomeMethod()

{

}

 
然后在运行时我们可以截获用户的调用,得到用户的角色,并检查数据库中Func1功能是否可以被该用户使用(至于维护数据库管理角色和功能关系的部分,就不在这里说了)。是不是想到AOP了,是有点象,可能这也算一种AOP的实现吧。刚开始看一些AOP的东西,还不太清楚 
回到正题,至少对于权限控制的主题,.net实际上提供了截获调用的方法,而且非常简单。要做到这一点,首先是编写一个CodeAccessSecurityAttribute的继承类,也就是我们的CustomSecurityAttribute类。在这个Attribute类中加入属性FuncID,并在构造函数中调用CodeAccessSecurityAttribute的构造函数。如果对Attribute不熟悉,可以参考这篇文章:
http://www.codeproject.com/csharp/dotnetattributes.asp
CodeAccessSecurityAttribute定义了一个抽象方法CreatePermission,我们必须在继承类中实现这个方法,CreatePermission方法要求返回一个IPermission接口,这个接口也是我们要实现的,在实现IPermission接口之前,我们先看一下CustomSecurityAttribute的完整代码:

[AttributeUsage(AttributeTargets.All, AllowMultiple=false, Inherited=true)]

[Serializable]

public sealed class CustomSecurityAttribute : CodeAccessSecurityAttribute

{

     public CustomSecurityAttribute(SecurityAction action) : base(action)

     {

     }

 

     private string _funcID;

 

     public string FuncID 

     {

         get

         {

              return _funcID;

         }

         set

         {

              _funcID = value;

         }

     }

 

     public override IPermission CreatePermission()

     {

         return new CustomPermission(_actionDomain);

     }

}

 

 

很简单吧,上面代码里的CustomPermission类是实现了IPermission接口的类,我们接下来要实现它。

 

我们已经实现了CustomSecurityAttribute类,这个比较简单,但是,为了让这个Attribute类正常工作,我们必须写一个IPermission接口的实现。既然CustomSecurityAttribute类从CodeAccessSecurityAttribute继承,似乎IPermission的实现类应该从CodeAccessPermission继承,但是我尝试了很久一直存在问题,要么编译不通过,要么执行时没有任何效果。想来应该是自己的代码有问题,不过咱有土办法,既然只是要求一个IPermission接口,那我们就直接写IPermission接口的实现好了,谁知道CodeAccessPermission类里面都写了写什么。对了,可以用反编译工具看,等以后再研究吧,现在先把直接实现IPermission接口的东东贴出来,至少这个是可以工作的
IPermission有5个接口方法,分别是Copy, Union, IsSubsetOf, Intersect, Demand,这里面最重要的方法是Demand,这里我们已经可以看到.net安全机制如何处理的了。
当调用代码访问带有SecurityAttribute基础属性的安全对象时,SecurityAttribute的CreatePermission方法被调用,创建出IPermission接口对象,然后,IPermission接口的Demand方法被调用以检查权限,如果通过,则继续,否则,Demand方法抛出安全异常,用户无法访问安全对象。
对于Demand方法的实现并没有限制,那么我们当然可以实现诸如从数据库读取角色/功能对应信息,从而判断用户是否具有访问权限。角色信息可以从当前上下问的IPrincipal基础类中得到,功能信息么,也很简单,CustomSecurityAttribute记录有FuncID,而IPermission对象是由CustomSecurityAttribute创建的,在创建的时候通过构造函数传递过来就可以了,下面给出IPermission继承类的部分实现代码:

     public sealed class CustomPermission : IPermission

     {

         public CustomPermission()

         {

         }

 

         public CustomPermission(string funcID)

         {

              _funcID = funcID;

         }

 

         public CustomPermission(PermissionState state) //据MSDN文档称必须实现这个构造函数

         {

         }


        
private string _funcID;


         public void Demand()

         {

              if (!CustomPermission.CheckPermission(_funcID))

                   throw new SecurityException("Access deny");

         }

         static private bool CheckPermission(string funcID)

         {

              if (funcID == "Func1")//在这里检查用户权限

                   return true;

 

              return false;

         }

         //其他方法略

     }


上面用一个静态方法CheckPermission实现具体检查权限的功能,实际的代码需要读取用户上下文的IPrincipal对象,通过其他对象从数据库中得到Func1功能对应的角色,然后检查IPrincipal是否包含这些角色,这些代码这里就略过了

大功告成了吗?没有。IPermission的其他方法还需要一一实现,当然可以先写一个空函数体在那里。更重要的是,IPermission接口继承自ISecurityEncodable接口,而这个接口的两个方法重要性不亚于Demand方法,它们是FromXml和ToXml。其中ToXml方法用来在编译期间为assembly注入metadata数据,又看到AOP的影子了,回头得好好研究研究这个。废话不说了,下面给出这两个方法的实现代码:

         public void FromXml(SecurityElement e)

         {

              String name = e.Attribute("class");

 

              // Make sure we are not converting something else:

              if (name != typeof(CustomPermission).AssemblyQualifiedName)

                   throw new ArgumentException("Wrong SecurityElement");

 

              String version = e.Attribute("version");

 

              if (version != "1.0")

                   throw new ArgumentException("Version " + version + " does not match current version of the permission");

 

              String funcid = e.Attribute("funcid");

 

              _funcID = funcid;   

         }

 

         public SecurityElement ToXml()

         {

              SecurityElement Ret = new SecurityElement("IPermission");

              String name = typeof(CustomPermission).AssemblyQualifiedName;

 

              Ret.AddAttribute("class", name);

 

              Ret.AddAttribute("version", "1.0");

 

              Ret.AddAttribute("funcid", _funcid);

 

              return Ret;

         }

 


好了,现在我们的定制安全机制框架代码算是完成了,最后要注意的一点是:CustomSecurityAttribute和CustomPermission必须在强名字的dll中实现,并且必须注册到GAC,否则,使用它们的assembly将无法正常编译。强名字不说了,注册GAC这里介绍个技巧,就是可以在Project Property的Pre-Build Event和Post-Build Event中加入从GAC删除和加入GAC的命令行,这样,每次编译是会自动更新GAC,否则调试的时候有的烦了

写了那么多,其实有些东西也是一知半解,请精通此道的大拿指正


 

关于Chrome的安全机制

Chrome采用的是多进程结构,进程类型主要有以下几种:1)主进程:负责所有资源管理、系统交互,前者包括bookmark、cookie、history管理等;后者包括屏幕绘制、处理keyboard/m...
  • winsunxu
  • winsunxu
  • 2011年05月20日 00:27
  • 1756

.NET中对类的扩展

概要:.NET对类的扩展包含两种方法,一种是扩展方法,一种是部分类;扩展方法:扩展方法可以使你来扩展一个已存在的类型,增加它的方法,而无需继承它或者重新编译。所以不像为对象写助手方法,扩展方法可以直接...
  • liaoxiaoli99
  • liaoxiaoli99
  • 2011年01月27日 11:22
  • 2518

JAVA安全机制

1,java.policy设置文件访问权限:java.io.FilePermissioneg: grant codeBase "http://www.pepress.com.cn/-" {      ...
  • mingde_he
  • mingde_he
  • 2010年08月23日 23:31
  • 6196

数据库系统的安全机制

 数据库系统的安全机制通常有以下几种:1.用户标识和鉴别    用户标识就是用户向系统出示的身份证明,这个证明形式可以是多样的,比如最简单的用户名和密码形式,数字证书,智能卡,个人生理特征(指纹),当...
  • gaohua027
  • gaohua027
  • 2007年03月07日 11:41
  • 1602

SQL Server的安全机制一般主要包括三个方面:

服务器级别的安全机制:这个级别的安全性主要通过登录帐户进行控制,要想访问一个数据库服务器,必须拥有一个登录帐户。登录帐户可以是Windows账户或组,也可以是SQL Server的登录账户。登录账户可...
  • gengkunpeng
  • gengkunpeng
  • 2010年11月04日 14:02
  • 826

.Net3.5之扩展方法

今天偶尔看了下.Net3.5的新特性介绍,其中有一点感觉挺吸引人----扩展方法。扩展方法可以在没有继承的情况下扩展一个已存在的类型,增加它的方法。通过下面这个示例,可以清楚地理解之。项目中我们经常要...
  • jtlyr
  • jtlyr
  • 2011年05月04日 12:10
  • 1476

操作系统的基本安全机制

下面说一下操作系统基本安全机制的实现 CPU模式和保护环,操作系统使用保护环机制确保进程不会彼此之间对系统重要组件产生影响。保护环对工作在环内的进程能够做什么,能够执行什么命令做出了严格...
  • ShaoqunLiu
  • ShaoqunLiu
  • 2016年08月12日 21:19
  • 1822

Hadoop 2.0 (YARN)中的安全机制概述

写在前面 安全管理是Hadoop中最复杂的、最难懂和最晦涩的模块,涉及到Hadoop的各个分支和每个分支的各个服务与组件,为了方便大家详细了解Hadoop内部的安全机制实现和各个验证流程,A...
  • liuj2511981
  • liuj2511981
  • 2013年12月10日 11:41
  • 1153

windows安全机制

1.GS安全编译原理选项的保护 攻击方法: 利用未被保护的内存突破GS; 覆盖虚函数突破GS; 将虚函数的调用地址改为自己的地址 攻击异常处理突破GS; char buf[200]...
  • moshangyanyuyao
  • moshangyanyuyao
  • 2013年12月14日 16:44
  • 940

linux安全机制学习

linux安全机制学习 曾经一度想学来着,今天看到一个链接,讲的很好,算是写一下加深印象吧 1 栈溢出保护 在程序编译的时候使用-fno-stack-protector标...
  • qq_20307987
  • qq_20307987
  • 2016年05月03日 21:17
  • 1764
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:扩展.net安全机制
举报原因:
原因补充:

(最多只允许输入30个字)