您的位置:首页 > 其它

构建基于角色、由应用程序管理的授权框架

2009-02-25 08:56 465 查看
构建基于角色、由应用程序管理的授权框架
安全性是一个非常大的课题,本篇文章旨在探讨授权部分。
如果你不理解安全性相关概念,可以参考如下几篇文章:
1、Web 应用程序安全框架:http://erpcrm.cnblogs.com/articles/234776.html
2、设计由应用程序管理的授权:http://erpcrm.cnblogs.com/articles/234793.html
3 、.net 基于角色的安全性介绍 http://msdn.microsoft.com/library/chs/?url=/library/CHS/cpguide/html/cpconIntroductionToRole-BasedSecurity.asp

本文假设你对.net 安全性相关概念如Principal 和Identity有所了解。
一、分析
先看一个基于角色授权的需求:
在一个CRM系统中,用户 “zhangsan”属于销售部的一名普通员工,“lisi”是该销售部的部门经理,“zhangsan”作为一名销售员有创建新客户的权利(customer.add),删除客户的权利(customer.delete)只有部门经理才有。
这种需求,我们一般情况下,建立两个角色(employees,managers),zhangsan属于employees, lisi属于managers,
然后我们再定义employees有customer.add的权利,managers两个权利都有,这样就基本满足了这种需求。

现在有一个更深层次的需求:zhangsan作为销售员需要报销一些行销费用,在报销流程中,1000元以下的费用由部门经理审批,超过1000元的由总经理审批,类似这样的需求,我们认为属于业务逻辑范畴,本授权框架不解决类似问题。

本框架的数据持久部分如下图:
本持久部分是该授权框架的一个持久实现,本框架数据持久部分采用porvider模型,允许你定义自己的持久实现。



二 利用.net实现该框架
在.net中基于角色安全性的两个重要概念就是 Principal(主体),Identity(标示)。
在该框架中 ECubePrincipal 实现了IPrincipal接口,ECubeIdentity 实现了IIdentity接口。


using System;


using System.Runtime.Serialization;


using System.Configuration;




namespace ECube.Business.Security






{


[SerializableAttribute]


public class ECubeIdentity : System.Security.Principal.IIdentity






{


private string _Name;


private string _AuthenticationType;


private bool _IsAuthenticated;






public ECubeIdentity()






{


_AuthenticationType = "ECubeCustom";


}


internal ECubeIdentity(String name, Boolean isAuthenticated)






{


_Name = name;


_IsAuthenticated = isAuthenticated;


}




public string Name






{


get






{


return _Name;


}


}


public bool IsAuthenticated






{


get






{


return _IsAuthenticated;


}


}


public string AuthenticationType






{


get






{


return _AuthenticationType;


}


}


}


}



上面这个是ECubeIdentity的源码,比较简单,没啥可说的。
下面看看ECubePrinicpal:


using System;


using System.Collections.Generic;


using System.Text;


using System.Security;


using System.Security.Principal;


using System.Web.Security;


using ECube.Business.SystemFramework;


using ECube.Business.Security.Data;




namespace ECube.Business.Security






{


[SerializableAttribute]


public class ECubePrincipal : IPrincipal






{


IIdentity _Identity;


private static IUserProvider _UserProvider;


private static IRoleProvider _RoleProvider;


private static IPermissionProvider _PermissionProvider;


private static String[] _Roles;




private Dictionary<String, Boolean> permissions = null;




public ECubePrincipal(IIdentity identity)






{


_Identity = identity;




//如果在ASP.NET 中是Forms授权


if(identity is System.Web.Security.FormsIdentity)






{




//检查Membership.Provider是否实现 IUserProvider;


if (!(System.Web.Security.Membership.Provider is IUserProvider))






{


throw new SecurityException("System.Web.Security.Membership.Provider Must is IUserProvider Type.");


}


//检查Roles.Provider是否实现 IRoleProvider;


if (!(System.Web.Security.Roles.Provider is IRoleProvider))






{


throw new SecurityException("System.Web.Security.Roles.Provider Must is IRoleProvide Type.");


}




_UserProvider = Membership.Provider as IUserProvider;


_RoleProvider = Roles.Provider as IRoleProvider;


}


else if(identity is System.Security.Principal.WindowsIdentity)






{




}


else if(identity is System.Web.Security.PassportIdentity)






{




}


else if(identity is System.Security.Principal.GenericIdentity)






{




}


else if(identity is ECubeIdentity)






{




}


else






{




}




//取得该用户的 “许可集”


permissions = PermissionProvider.GetPermissions(identity.Name);




}






/**//// <summary>


/// 返回角色数据提供者。


/// </summary>


public static IRoleProvider RoleProvider






{


get






{


if (_RoleProvider == null)






{


//首先检查当前应用程序的配置中是否指定了 角色提供者


String roleProviderName = BizApplication.Current.Parameters["RoleProviderName"].Value;


//如果没有


if (String.IsNullOrEmpty(roleProviderName))






{


//取得配置文件中Role段的默认角色提供者名字


roleProviderName = BizSecuritySection.Role.DefaultProvider;


}




if (!String.IsNullOrEmpty(roleProviderName))






{


//根据名字,取得对应的Provider


_RoleProvider = BizSecuritySection.Role.GetProvider(roleProviderName);


}




//如果还没有取到,并且定义了提供者


if (_RoleProvider == null && BizSecuritySection.Role.Providers.Count > 0)






{


//取得第一个


_RoleProvider = BizSecuritySection.Role.GetProvider(BizSecuritySection.Role.Providers[0]);


}




//如果还没取得


if (_RoleProvider == null)






{


//使用默认的。


_RoleProvider = new Role();


}




}


return _RoleProvider;


}


}




/**//// <summary>


/// 返回用户提供者。


/// </summary>


public static IUserProvider UserProvider






{


get






{


if (_UserProvider == null)






{


//首先检查当前应用程序的配置中是否指定了


String userProviderName = BizApplication.Current.Parameters["UserProviderName"].Value;




//如果没有


if (String.IsNullOrEmpty(userProviderName))






{


//取得配置文件中User段的默认提供者名字


userProviderName = BizSecuritySection.User.DefaultProvider;


}




if (!String.IsNullOrEmpty(userProviderName))






{


//根据名字,取得对应的Provider


_UserProvider = BizSecuritySection.User.GetProvider(userProviderName);


}


//如果还没有取到,并且定义了提供者


if (_UserProvider == null && BizSecuritySection.User.Providers.Count > 0)






{


//取得第一个


_UserProvider = BizSecuritySection.User.GetProvider(BizSecuritySection.User.Providers[0]);


}




//如果还没取得


if (_UserProvider == null)






{


//使用默认的。


_UserProvider = new User();


}


}




return _UserProvider;


}


}




/**//// <summary>


/// 返回许可提供者.


/// </summary>


public static IPermissionProvider PermissionProvider






{


get






{




if (_PermissionProvider == null)






{


//首先检查当前应用程序的配置中是否指定了


String permissionProviderName = BizApplication.Current.Parameters["PermissionProviderName"].Value;


//如果没有


if (String.IsNullOrEmpty(permissionProviderName))






{


//取得配置文件中User段的默认提供者名字


permissionProviderName = BizSecuritySection.Permission.DefaultProvider;


}


if (!String.IsNullOrEmpty(permissionProviderName))






{


//根据名字,取得对应的Provider


_PermissionProvider = BizSecuritySection.Permission.GetProvider(permissionProviderName);


}


//如果还没有取到,并且定义了提供者


if (_PermissionProvider == null && BizSecuritySection.Permission.Providers.Count > 0)






{


//取得第一个


_PermissionProvider = BizSecuritySection.Permission.GetProvider(BizSecuritySection.Permission.Providers[0]);


}


//如果还没取得


if (_PermissionProvider == null)






{


//使用默认的。


_PermissionProvider = new Permission();


}


}


return _PermissionProvider;


}


}






/**//// <summary>


/// 注销


/// </summary>


public void Logout()






{


this._Identity = null;


System.Threading.Thread.CurrentPrincipal = null;


}






/**//// <summary>


/// 登录,这是一个静态方法


/// </summary>


/// <param name="usrName">用于验证的用户名。</param>


/// <param name="usrPwd">用于验证的密码</param>


/// <param name="isSecurity">是否使用安全的提示,如果否:当验证错误时,提示非常明确,如“没有找到该用户!”,“密码错误!”。


/// 否则,给出非常模糊的提示。


/// </param>


public static void Login(string usrName, string usrPwd, bool isSecurity)






{




try






{


if (_UserProvider != null)






{


if (_UserProvider.ValidateUser(usrName, usrPwd, isSecurity))






{






DSSecurity.SECRolesDataTable roleTable = RoleProvider.GetRolesForUser(usrName);




_Roles = new String[roleTable.Count];


for (int i = 0; i < roleTable.Count; i++)






{


_Roles[i] = roleTable[i].Name;


}






IIdentity identity = new ECubeIdentity(usrName, true);


System.Threading.Thread.CurrentPrincipal = new ECubePrincipal(identity );


return;


}




}


}


catch (System.Exception ex)






{


if (ex is SecurityException)






{


throw;


}


else






{


//做一些记录等工作。


}


}






}








/**//// <summary>


/// 检查权限。


/// </summary>


/// <param name="permissionKey">权限的键:如在增加客户的权限可以描述为:“Customer.add”</param>


/// <returns></returns>


public Boolean CheckPermission(String permissionKey)






{


if (String.IsNullOrEmpty(permissionKey))






{


return false;


}




if (_Identity == null)






{


return false;


}




if (!_Identity.IsAuthenticated || permissions == null || permissions.Count == 0)






{


return false;


}




return permissions[permissionKey];




}








IPrincipal 成员#region IPrincipal 成员




public IIdentity Identity






{


get






{


if (_Identity == null)






{


_Identity = new ECubeIdentity("guest",false);


}


return _Identity;




}


}




public bool IsInRole(string role)






{


throw new Exception("The method or operation is not implemented.");


}




#endregion


}


}



如果你只是想使用本框架的话,你接触到的只会是ECubePrincipal类。如果你想实现自己的持久,你可以实现
IRoleProvider、IUserProvider、IPerssionsProvider接口,当然了还需要一些配置(不过我会实现一个工具来完成这个过程)
如何使用本框架进行登录验证呢?
场景一:
考虑一个非ASP.NET 环境,你在登录窗口的登录按钮的CLICK 事件中,可以这样写:
{
if( ECubePrincipal.Login(usernmae,userpwd,true))
{
....
}
}
就这么简单。
场景二:
ASp.net环境,asp.net 中可能稍微复杂一些,因为asp.net 有自己的验证机制,但也不是没办法。
我们可以在Global.asax的方
法中写如下代码(当然你可以自己实现一个IhttpModule,不一定非得在Global.asax中)


void Applicaiton_AuthenticateRequest(object sender, EventArgs e)






{


if (sender == null)






{


return;


}




HttpContext Context = ((HttpApplication)sender).Context;


if (Context.User != null && !(Context.User is ECube.Business.Security.ECubePrincipal))






{


if (Context.User.Identity is FormsIdentity)






{


if (Membership.Provider is ECube.Business.Security.IUserProvider &&


Roles.Provider is ECube.Business.Security.IRoleProvider)






{


Context.User = new ECube.Business.Security.ECubePrincipal(Context.User.Identity);


}


}


else






{


Context.User = new ECube.Business.Security.ECubePrincipal(Context.User.Identity);


}


}




}



三、如何进行授权

验证授权验证非常简单:
class Customer
{
void Add()
{
ECubePrincipal princ = System.Threading.Thread.CurrentPrincipal as ECube.Business.Security.ECubePrincipal
if(princ != null && princ.CheckPermission("customer.add"))
{
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐