Evil 域

当Evil遇上先知

导航

ASP.NET 2.0相对于1.0的一个改进,在于提供了成员管理和角色管理功能。其中,角色管理功能,使程序开发时限定某些特定资源仅能够为某些特定用户所访问提供了很大的便利。在得到需求时,就可以把用户分成几个角色,程序对角色加以限制,而管理员可以把不同的人置于不同的角色,这样,一个灵活的权限访问系统就成型了。
这样一种模式,能够用10%的气力解决90%的问题。但企业应用中,剩下这10%的情况往往发生。例如,对于重置用户密码这样的“敏感”操作,仅允许管理员组的某一个用户来进行;又或者,管理员组中的用户可以删除用户,但不允许删除用户名为“Admin”的用户……针对这种百年一遇的情况(夸张了,其实企业往往会出现这种“怪怪”的需求),Memership结合Enterprise Library中的Security Application Block(SAB)提供的方法用起来屡试不爽。
以“只有Administrators组的名称为Admin的用户可以进行密码重置操作”这一条规则为例,来看看如何利用SAB来达到相应的目的。
第一步,在web.config里添加Security Application Block。

图1
第二步,在Authorization节里,添加一个Authorization Rule Provider

图2
第三步,在RuleProvider节里,添加一个Rule,命名为“CanResetUserPassword”,并且设置其表达式属性为“I:Admin AND R:Administrators”。

图3
第四步,建立一个SABHelper,用来判断此用户是否有权限执行某一个操作。

using System.Security.Principal;
using Microsoft.Practices.EnterpriseLibrary.Security;


        
/// <summary>
        
/// 用户是否允许执行某一操作
        
/// </summary>
        
/// <param name="identity">身份</param>
        
/// <param name="roles">角色</param>
        
/// <param name="ruleName">规则名称</param>
        
/// <returns></returns>

        public static bool CanUserPerformTask(IIdentity identity , string[] roles, string ruleName)
        
{

            IPrincipal principal 
= new GenericPrincipal(identity, roles);
            IAuthorizationProvider ruleProvider 
= AuthorizationFactory.GetAuthorizationProvider("RuleProvider");
            
bool authorized = ruleProvider.Authorize(principal, ruleName);
            
return authorized;
        }

最后,在业务逻辑中对当前用户进行校验,通过者方能执行:
        /// <summary>
        
/// 重置密码
        
/// </summary>
        
/// <param name="user">用户</param>
        
/// <param name="newPassword">新密码</param>

        public static void ResetPassword(MembershipUser user, string newPassword)
        
{
            
string tempPwd = user.ResetPassword();
            
            
if (SABHelper.CanUserPerformTask(HttpContext.Current.User.Identity, Roles.GetRolesForUser(HttpContext.Current.User.Identity.Name), AuthorizeRules.CanResetUserPassword.ToString()))
            {
                user.ChangePassword(tempPwd, newPassword);
            }

            
else
            
{
                
throw new Exception("当前用户没有足够的权限执行此操作!");
            }

        }
这样,当用户以Admin登录到系统时,可以正常的执行密码重置操作;但是,以其它用户登录,即使是Administrators的其他用户身份,都会抛出没有足够权限的异常。而且,由于这个“特权用户”是通过web.config来配置的,当需要增、删“特权用户”时,修改规则的表达式即可。
这么做也存在一些缺陷,首先,它需要管理员能够正确的书写规则中的表达式(虽然不难写),如果能够制作一个界面,就可以克服这一个缺陷;其次,用户信息保存在web.config中,修改时,一不小时就可能导致整个站点失效。针对第二个缺陷的解决,据说网上有网友做了存储在数据库中的Provider。