在基于“操作”的用户授权(二):定义操作授权 一文中,我介绍了如何使用System.Attribute类在代码级别定义操作授权。现在来看看如何检索和验证操作授权。
检索操作授权
检索操作授权的目的是为了获取当前系统中的所有操作授权信息,以方便管理员进行授权管理。授权检索的基本方法是通过System.Reflection命名空间下的相关类获取BIN文件夹或者App_Code文件夹下的所有类,获取该类的方法信息(MethodInfo),然后调用MehodInfo.GetCustomAttributes函数获取已经定义的授权信息。下面是从网站BIN目录中获取授权信息的代码:
public static HybridDictionary GetAuthorizationFromDll()
{
HybridDictionary authorizations = new HybridDictionary();
string path = HttpContext.Current.Server.MapPath("~/Bin");
string[] files = Directory.GetFiles(path, "*.DLL");
foreach (string file in files)
{
System.Reflection.Assembly asm = System.Reflection.Assembly.LoadFile(file);
Type[] types = asm.GetTypes();
foreach (Type type in types)
{
if (!type.IsAbstract)
{
MethodInfo[] infos = type.GetMethods();
foreach (MethodInfo info in infos)
{
OperationAuthorizationAttribute[] auths = info.GetCustomAttributes(typeof(OperationAuthorizationAttribute), true) as OperationAuthorizationAttribute[];
foreach (OperationAuthorizationAttribute auth in auths)
{
if (!authorizations.Contains(auth.ID))
authorizations.Add(auth.ID, auth);
}
}
}
}
}
return authorizations;
}
验证操作授权
验证操作授权的目的是判断当前用户是否具有执行某个操作的权限。验证操作授权的基本方法和检索操作授权基本相同,首先获取MethodInfo,然后调用MehodInfo.GetCustomAttributes函数获取授权信息,最后调用当前用户身份的IsInAuthorizatons函数进行授权验证。下面是对操作授权进行验证的代码:
public static bool IsUserAuthorized(MethodBase methodInfo)
{
OperationAuthorizationAttribute authorization = null;
if (methodInfo != null)
authorization = Attribute.GetCustomAttribute(methodInfo, typeof(OperationAuthorizationAttribute), true) as OperationAuthorizationAttribute;
if (authorization != null)
return IsUserAuthorized(authorization.ID);
else
return true;
}
public static bool IsUserAuthorized(Guid guid)
{
if (HttpContext.Current.Request.IsAuthenticated && HttpContext.Current.User is OperationAuthorizationPrincipal)
{
OperationAuthorizationPrincipal principal = HttpContext.Current.User as OperationAuthorizationPrincipal;
return principal.IsInAuthorization(guid);
}
else
return IsGuestAuthorized(guid);
}
通常会在以下两种情况中验证操作授权:
1、在执行操作前验证
这种情况通常是程序在执行某个操作前验证用户的操作授权,从而控制页面或者控件是否呈现某些内容给用户。例如一个用于文章管理的自定义控件,当用户具有"添加文章"的权限时,向用户呈现一个“添加文章”按钮;反之,如果用户不具有“添加文章”权限,则不呈现“添加文章”按钮。应该说这种验证是不安全的,因为程序员可能不进行操作前验证而直接执行操作。操作前验证通常是通过类的实例来进行的,获取MethodInfo的方法如下:
protected void Page_Load(object sender, EventArgs e)
{
OperationAuthorizationProvider provider = Tiray.Security.Utility.DataProvider;
。。。。。。
if (!Utility.IsUserAuthorized(provider.GetType().GetMethod("AddAuthorization")))
btn_Add.Enabled = false;
。。。。。。
}
}
2、在执行操作时验证
这种情况通常是定义了操作授权的函数在被调用时自行验证授权,这是在代码级别进行的授权验证,获取MethodInfo的方法方法和上面略有不同,是在函数内部调用MethodInfo.GetCurrentMethod方法实现的。下面是扩展System.Web.Security.SqlProvider类以支持操作授权的部分代码:
public override void AddUsersToRoles (string[] usernames,string[] roleNames)
{
if (Tiray.Security.Utility.IsUserAuthorized(System.Reflection.MethodInfo.GetCurrentMethod()))
base.AddUsersToRoles(usernames,roleNames);
else
throw new OperationNotAuthorizedExcption("AddUsersToRoles is not authorized");
}
结语
在《基于“操作”的用户授权》系列文章中,我从语义分析入手,详细讨论了如何扩展ASP.NET安全性以实现自定义的授权模式。这种“基于‘操作’”的授权模式目前已经应用于我开发的一个网站项目中,应该说到目前为止,使用效果还是不错的。
这个系列文章如果说有什么不足的话,就是没有讨论如何实现数据提供器(DataProvider)以保存和检索授权信息,不过对于各位C#高手来说,这应该不是什么难题了吧!
参考:
基于“操作”的用户授权(一):基本分析
基于“操作”的用户授权(二):定义操作授权
基于“操作”的用户授权(三):扩展ASP.NET安全性