Asp.net使用IIdentity和IPrincipal实现自定义身份及权限认证

1,Webform通过继承BasePage页实现角色权限控制
context.User中保存的信息就是相关的角色与权限信息。Context.User类型为System.Security.Principal.IPrincipal;
Context.User.Identity为System.Security.Principal.IIdentity,因此只要我们实现的上述的两个接口便可实现我们所需的方案
在传统的.NET中,我们可以通过
User.Identity.Name;//获取用户名  
User.Identity.IsAuthenticated;//判断用户是否己验证  
User.IsInRole("Admin");//判断用户是否含有指定角色
但这样的机制,在实际开发中,难以满足开发需要.我们需要获取更多信息,或者进行更详细的权限判断。 
我们可以通过自定义Identity和Principal进行实现!
///<summary>/// 自定义当前用户标识对象
    ///</summary>publicclass MyIdentity:IIdentity
    {
     //用户属性(可自定义更多信息)
        privatestring _userName;//用户账号privatestring _departmnet;//用户所在部门privatestring _phone;//用户联系电话///<summary>/// 用户账号
        ///</summary>publicstring UserName
        {get { return _userName; }        }
 
        ///<summary>/// 用户所在部门
        ///</summary>publicstring Departmnet
        {get { return _departmnet; }        }
 
        ///<summary>/// 用户电话
        ///</summary>publicstring Phone
        {get { return _phone; }        }
 
        ///<summary>/// 构造函数,根据用户名
        ///</summary>///<param name="UserName"></param>public MyIdentity(string UserName)
        {
            //根据UserName查询数据库获得以下数据 
               this._userName = "abc"; 
            this._departmnet = "行政部"; 
            this._phone = "123456"; 
        }
 
        ///<summary>/// 构造函数,根据用户ID 
        ///</summary>///<param name="UserID"></param>public MyIdentity(int UserID) 
        { 
            //根据UserID查询数据库获得以下数据 this._userName = "abc"; 
            this._departmnet = "行政部"; 
            this._phone = "123456"; 
        }
 
        #region 基本属性 
        ///<summary>/// 返回验证方式 
        ///</summary>publicstring AuthenticationType 
        { 
            get { return"Form"; } 
        }
 
        ///<summary>/// 是否验证 
        ///</summary>publicbool IsAuthenticated 
        { 
            get { returntrue; } 
        }
 
        ///<summary>/// 返回用户 
        ///</summary>publicstring Name 
        { 
            get { return _userName; } 
        } 
        #endregion
    }
 
 
    ///<summary>/// 当前用户安全上下文信息 
    ///</summary>publicclass MyPrincipal:IPrincipal 
    { private IIdentity _identity;//用户标识 private ArrayList _permissionList;//权限列表 ///<summary>/// 返回用户权限列表 
        ///</summary>public ArrayList PermissionList 
        { get { return _permissionList; }         }
  
        ///<summary>/// 获取当前用户标识 
        ///</summary>public IIdentity Identity 
        { get { return _identity; }         }
 
        ///<summary>/// 当前用户是否指定角色(采用权限值方式,此处返回false) 
        ///</summary>///<param name="role"></param>///<returns></returns>publicbool IsInRole(string role) 
        { returnfalse;        }
 
        ///<summary>/// 构造函数,用户名构造 
        ///</summary>///<param name="UserName"></param>public MyPrincipal(string UserName) 
        { 
            _identity = new MyIdentity(UserName); 
            //以下权限根据UserName获取数据库用户拥有的权限值,此次省略 
            _permissionList = new ArrayList(); 
            _permissionList.Add(1); 
            _permissionList.Add(2); 
            _permissionList.Add(3); 
        }
 
        ///<summary>/// 构造函数,用户ID构造 
        ///</summary>///<param name="UserID"></param>public MyPrincipal(int UserID) 
        { 
            _identity = new MyIdentity(UserID); 
            //以下权限根据UserName获取数据库用户拥有的权限值,此次省略 
            _permissionList = new ArrayList(); 
            _permissionList.Add(1); 
            _permissionList.Add(2); 
            _permissionList.Add(3); 
        }
 
        ///<summary>/// 判断用户是否拥有某权限 
        ///</summary>///<param name="permissionid"></param>///<returns></returns>publicbool IsPermissionID(int permissionid) 
        { 
            return _permissionList.Contains(permissionid); 
        } 
    }
 
 
上面我们己实现了自定义,Identity和Principal。 
我们可以在页面这样使用Identity。
//页面中输出自定义用户信息
<%=(User.Identity as ContextUser.MyIdentity).Name %>//用户账号
<%=(User.Identity as ContextUser.MyIdentity).Phone %>//用户电话 
<%=(User.Identity as ContextUser.MyIdentity).Departmnet %>//用户所在部门 
自定义显示用户信息后,我们接着利用Principal进行权限验证和控制 
在Asp.net Web模式下,使用方式: 
首先,我们先做一个权限验证基类!
///<summary>///权限验证基类 
///</summary>publicclass BasePaper:System.Web.UI.Page 
{ 
    public BasePaper() 
       {        }
 
    protectedoverridevoid OnInit(EventArgs e) 
    { 
        BasePage_Load(); 
    }
 
    ///<summary>/// 设置权限,默认值为0 
    ///</summary>publicvirtualint PermissionID 
    {         get { return0; }     }
 
    ///<summary>/// 验证方法 
    ///</summary>///<param name="sender"></param>///<param name="e"></param>privatevoid BasePage_Load() 
    { 
        //权限检查 bool Permission = true;//初始值为没有权限  
                //这一步很重要,要代替.NET的自身的User. 
                 HttpContext.Current.User = new ContextUser.MyPrincipal(HttpContext.Current.User.Identity.Name); 
 
        if ((User as account.ContextUser.MyPrincipal).PermissionList.Contains(PermissionID)) 
        { 
            Permission = false;//验证通过         }
 
        if (Permission)//权限验证不通过         { 
            Response.Clear(); 
            Response.Write("<script language="javascript">alert("对不起,你没有权限进入");history.go(-1);</script>"); 
            Response.End(); 
        } 
    } 
}
 

OK,到了验证页的时候了。
publicpartialclass ascx_Add :BasePage 
{ 
    publicoverrideint PermissionID 
    { 
        get 
        { 
            return13;//返回要验证权限值         } 
    }
 
    protectedvoid Page_Load(object sender, EventArgs e) 
    {     } 
}
 
事实上,在Asp.net MVC模式,更容易对权限进行控制,可以进行更多的细化,对每个动作进行控制。 
首先,先实现一个权限验证基类:
    ///<summary>/// 权限验证基类 
    /// 2011.7.3 
    ///</summary>publicclass BasePage : AuthorizeAttribute 
    { 
        ///<summary>/// 权限值 
        ///</summary>privateint _permissionID = 0;
 
        ///<summary
/// 权限值
        ///</summary>publicint PermissionID 
        { 
            get { return _permissionID; } 
            set { _permissionID = value; } 
        }
 
        ///<summary>/// 在过程请求授权时调用。  
        ///</summary>///<param name="filterContext">对象包括控制器、HTTP 上下文、请求上下文、操作结果和路由数据。</param>publicoverridevoid OnAuthorization(AuthorizationContext filterContext) 
        { 
            if (HttpContext.Current.User.Identity.IsAuthenticated) 
            { 
                //这一步很重要,要代替.NET的自身的User.
                ContextUser.MyPrincipal MyPrincipal = new ContextUser.MyPrincipal(HttpContext.Current.User.Identity.Name); 
                HttpContext.Current.User = MyPrincipal; 
 
                if ((!MyPrincipal.ISPermissionID(_permissionID)) && (_permissionID != 0)) 
                { 
                    HttpContext.Current.Response.Clear();
 
                    HttpContext.Current.Response.Write("<script defer>window.alert('无权操作!');history.back();</script>");
 
                    HttpContext.Current.Response.End();
 
                    filterContext.Result = new EmptyResult(); 
                } 
            } 
            else 
            { 
                FormsAuthentication.SignOut(); 
                HttpContext.Current.Response.Clear(); 
                HttpContext.Current.Response.Write("<script defer>window.alert('无权操作!或当前登录用户已过期!\n请重新登录或与管理员联系!');</script>"); 
                HttpContext.Current.Response.End(); 
                filterContext.Result = new EmptyResult(); 
            } 
        } 
    }
 

回到控制器,进行权限验证
        [BasePage(PermissionID = 13)]//返回要验证权限值 public ActionResult Index() 
        { 
           //        }
 
无论对Asp.net Form或者Aap.net MVC,都在一个按钮级的权限控制,
那对于,按钮级的权限如何进行控制昵?
 
看下面代码
    //控制删除按扭的显示
 
    <% if((User as account.ContextUser.MyPrincipal).PermissionList.Contains(13) {%> 
    <input type="submit" name="button" id="button" value="删除" /> 
    <%} %>
 

至此,如何实现自定义Identity和Principal,进行整合更多用户信息,和权限验证。
2,通过HttpMoudle注册来实现角色权限控制。继承接口和上面一样
创建一个User类实现IIdentity接口 重写相应的方法
publicclass User : IIdentity
    {
        privateint _id;
        privatestring _userName;
        privatestring _password;
        privatebool _isAuthenticated;
        #region properties
        publicvirtualint Id
        {
            get { returnthis._id; }
            set { this._id = value; }
        }
        publicvirtualstring UserName
        {
            get { returnthis._userName; }
            set { this._userName = value; }
        }
        publicvirtualstring Password
        {
            get { returnthis._password; }
            set { this._password = value; }
        }
        //是否通过认证publicvirtualbool IsAuthenticated
        {
            get { returnthis._isAuthenticated; }
            set { this._isAuthenticated = value; }
        }
        //重写为用户IDpublicvirtualstring Name
        {
            get
            {
                if (this._isAuthenticated)
                    returnthis._id.ToString();
                elsereturn"";
            }
        }
        publicvirtualstring AuthenticationType
        {
            get { return"CuyahogaAuthentication"; }
        }
        public User()
        {
            this._id = -1;
            this._isAuthenticated = false;
        }
    }
创建一个CuyahogaPrincipal类实现IPrincipal接口
publicclass CuyahogaPrincipal : IPrincipal
    {
        private User _user;
        // 返回一个现实IIdentity接口的user对象public IIdentity Identity
        {
            get { returnthis._user; }
        }
        // 当前用户是否属于指定角色 在以后的权限认证中可以使用 也可以使用User类中的相关方法来代替publicbool IsInRole(string role)
        {
            foreach (Role roleObject inthis._user.Roles)
            {
                if (roleObject.Name.Equals(role))
                    returntrue;
            }
            returnfalse;
        }
        ///初始化 若user通过授权则创建public CuyahogaPrincipal(User user)
        {
            if (user != null && user.IsAuthenticated)
            {
                this._user = user;
            }
            else
            {
                thrownew SecurityException("Cannot create a principal without u valid user");
            }
        }
    }
创建一个实现IHttpModule的AuthenticationModule类
publicclass AuthenticationModule : IHttpModule
    {
        privateconstint AUTHENTICATION_TIMEOUT = 20;
 
        public AuthenticationModule()
        {
        }
 
        publicvoid Init(HttpApplication context)
        {
            context.AuthenticateRequest += new EventHandler(Context_AuthenticateRequest);
        }
 
        publicvoid Dispose()
        {
            // Nothing here            }
 
        //登录时 验证用户时使用publicbool AuthenticateUser(string username, string password, bool persistLogin)
        {
            //数据访问类
            CoreRepository cr = (CoreRepository)HttpContext.Current.Items["CoreRepository"];
            string hashedPassword = Encryption.StringToMD5Hash(password);
            try
            {
                //通过用户名密码得到用户对象
                User user = cr.GetUserByUsernameAndPassword(username, hashedPassword);
                if (user != null)
                {
                    user.IsAuthenticated = true;
                    //string currentIp = HttpContext.Current.Request.UserHostAddress;
                    //user.LastLogin = DateTime.Now;
                    //user.LastIp = currentIp;
                    // Save login date and IP 记录相关信息                    cr.UpdateObject(user);更新用户授权通过信息
                    // Create the authentication ticket
                    HttpContext.Current.User = new CuyahogaPrincipal(user);  //通过授权                    FormsAuthentication.SetAuthCookie(user.Name, persistLogin);
                    returntrue;
                }
                else
                {
                    //log.Warn(String.Format("Invalid username-password combination: {0}:{1}.", username, password));returnfalse;
                }
            }
            catch (Exception ex)
            {
                thrownew Exception(String.Format("Unable to log in user '{0}': " + ex.Message, username), ex);
            }
        }
 
        ///<summary>/// Log out the current user.注销用户
        ///</summary>publicvoid Logout()
        {
            if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
            {
                FormsAuthentication.SignOut();
            }
        }
 
        privatevoid Context_AuthenticateRequest(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;
            if (app.Context.User != null && app.Context.User.Identity.IsAuthenticated)//若用户已经通过认证            {
                CoreRepository cr = (CoreRepository)HttpContext.Current.Items["CoreRepository"];
                int userId = Int32.Parse(app.Context.User.Identity.Name);
                User cuyahogaUser = (User)cr.GetObjectById(typeof(User), userId);//得到对应的cuyahogaUser对象
                cuyahogaUser.IsAuthenticated = true;
                app.Context.User = new CuyahogaPrincipal(cuyahogaUser);//将通过标准窗体认证的user替换成CuyahogaUser, cuyahogaUser包含更多的信息            }
        }
    }
登录时
protectedvoid btnLogin_Click(object sender, System.EventArgs e)
        {
            AuthenticationModule am = (AuthenticationModule)Context.ApplicationInstance.Modules["AuthenticationModule"];
            if (this.txtUsername.Text.Trim().Length > 0 && this.txtPassword.Text.Trim().Length > 0)
            {
                try
                {
                    if (am.AuthenticateUser(this.txtUsername.Text, this.txtPassword.Text, this.chkPersistLogin.Checked))
                    {
                        //通过认证                        Context.Response.Redirect(Context.Request.RawUrl);
                    }
                    else
                    {
                        //认证失败                    }
                }
                {
                }
            }
        }
退出登录用
protectedvoid btnLogout_Click(object sender, System.EventArgs e)
        {
            AuthenticationModule am = (AuthenticationModule)Context.ApplicationInstance.Modules["AuthenticationModule"];
            am.Logout();
            Context.Response.Redirect(Context.Request.RawUrl);
        }
这样就实现了身份认证功能

然后可以方便的实现权限认证
在User类中实现相应的权限逻辑 如: 表示当前用户是否有权限浏览指定的节点
publicbool CanView(Node node)
        {
            foreach (Permission p in node.NodePermissions)
            {
                if (p.ViewAllowed && IsInRole(p.Role))
                {
                    returntrue;
                }
            }
            returnfalse;
        }
在Page代码中嵌入验证代码即可
User CuyahogaUser =  this.User.Identity as User;
if(CuyahogaUser.CanView())
{
}
权限认证模块还是挺简单.
最后在web.config中对AuthenticationModule进行注册

转:https://blog.csdn.net/anihasiyou/article/details/79668267

原文地址:https://www.cnblogs.com/fanfan-90/p/12054791.html