经不住微软的诱惑,终于在新项目中采用标准的ASP.NET 2.0的membership role profile方案。但使用时发现.......这东西着实难用T_T。实现它并套用它花了1个星期,但实际使用起来,又感觉缩手缩脚的,尤其是获取用户的扩展信息及其繁杂。最终,又改回了自己套用以熟的ISecurity方案(见下),哈哈,改回原方案只用了一个下午,且代码清爽:)以下是个人对这套标准provider方案的看法:
RoleProvider 用于提供用户角色信息。设计得还行,没有什么冗余。
MembershipProvider 用于用户认证校验、登陆、注销处理。字段冗余,接口冗余,不一定都用得到。
ProfileProvider 用于保存用户扩展信息。实现及其繁琐,真是人见人厌,花见花蔫...
整体看来,这套方案涉及到了用户认证,角色,用户扩展信息的几个方面,是一套“看起来完美”的方案。但深入试用后发现,除了RoleProvider 以外,这套方案有过度设计的嫌疑。接口函数冗余度很大,且扩展很麻烦,要用到无数相关的类,而一般我只用到这么几个接口函数,用于认证和角色获取:
MembershipProvider.ValidateUser(...)
RoleProvider.GetAllRoles(...)
RoleProvider.GetRolesForUser(...)
RoleProvider.AddUsersToRoles(...)
至于ProfileProvider,它的本意是保存用户的扩展信息,但它的结构设计导致数据库批量查询的时候很麻烦且性能低下,另外接口代码也无比复杂,实现它无比繁琐,实在提不起用它的念头@_@。大家有没有什么好的建议或方法(尤其是保存用户扩展信息的方法),请各位博友不啻指教。至于RoleProvider 虽然没有冗余,但单用的话还是远远不够用的。如接口函数:string[] GetUsersForRole(string role) 只返回字符串数组,无法直接返回用户信息,又需要再次使用Membership 和 Profile 来获取扩展信息,无法一次到位。Membership也是如此,无法一次到位,我们习惯用两个字段来保存用户的信息:帐户和名称,而membership中只提供username这个属性,如果要批量获取用户清单,包括用户帐户和名称,怎么做?先获取帐户,再用profiile获取名称?彻底晕菜.....另外一点,最糟糕的是,这套方案都是在 System.Web 命名空间下实现的,附加了web下的处理逻辑,不通用,做windows程序的时候又无效了@!#%$%$#%@#$@....
牢骚发毕,反正我现在是放弃这套标准推荐方案了,彻底死心。以下是我现项目采用的用户角色认证的方案,感觉用起来比较方便,供大家参考。此外,大家有没有觉得.NET类库越设计越大,有点失控了(如有多少集合类可以用IList<T>替代?)?类库设计的原则应该是通用精简,而非所有功能都往上堆....至少,扩展的、不是都必用的类及接口不要往 system.dll, system.web.dll 里面塞.....
/// <summary>
/// 安全接口:用户、角色、资源、认证
/// </summary>
public interface ISecurity<T> : IDisposable where T : IUserInfo
{
// init
void Initialize(params string[] config);
// authenticate
bool ValidateUser(string userId, string password);
// create user object
T CreateUserObject();
// user
List<T> GetUsers(params string[] parameters);
T GetUser(string userId);
void CreateUser(ref T user);
void UpdateUser(ref T user);
void DeleteUser(string userId);
// role
string[] GetAllRoles();
string[] GetRolesForUser(string userId);
List<T> GetUsersInRole(string role);
bool IsUserInRole(string userId, string role);
void AddUserToRoles(string userId, string[] roles);
void RemoveUserFromRoles(string userId, string[] roles);
// resources
//string[] GetAllResources();
//string[] GetResourcesForUser(string userId);
//string[] GetUsersInResource(string resource);
}
/// <summary>
/// 基本用户信息接口
/// </summary>
public interface IUserInfo
{
string UserId { get; set; }
string UserName { get; set; }
string Password { get; set; }
string Organization { get; set; }
string Comment { get; set; }
string Status { get; set; }
void Clone(IUserInfo user);
}
对于每个应用只要实现ISecurity和IUserInfo接口就可以了。