扩展.net安全机制(续)
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,否则调试的时候有的烦了
写了那么多,其实有些东西也是一知半解,请精通此道的大拿指正
posted on 2004-04-30 11:04 vibration 阅读(1731) 评论(6) 编辑 收藏 举报