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

1,通过继承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");//判断用户是否含有指定角色
但这样的机制,在实际开发中,难以满足开发需要.仅仅通过User.Identity.Name;获取用户名,和User.Identity.IsAuthenticated;判断用户是否验证,是难以满足需要。如何获取用户更多信息,或者进行更详细的权限判断。 
我们可以通过自定义Identity和Principal进行实现!
/// 
    /// 自定义当前用户标识对象
    /// 
    public class MyIdentity:IIdentity
    {
        #region 用户属性(可自定义更多信息)
        private string _userName;//用户账号
        private string _departmnet;//用户所在部门
        private string _phone;//用户联系电话
        #endregion

        /// 
        /// 用户账号
        /// 
        public string UserName
        {
            get { return _userName; }
        }
 
        /// 
        /// 用户所在部门
        /// 
        public string Departmnet
        {
            get { return _departmnet; }
        }
 
        /// 
        /// 用户电话
        /// 
        public string Phone
        {
            get { return _phone; }
        }
 
        /// 
        /// 构造函数,根据用户名
        /// 
        /// 
        public MyIdentity(string UserName)
        {
            //根据UserName查询数据库获得以下数据 
            this._userName = "abc"; 
            this._departmnet = "行政部"; 
            this._phone = "123456"; 
        }
 
        ///  
        /// 构造函数,根据用户ID 
        ///  
        ///  
        public MyIdentity(int UserID) 
        { 
            //根据UserID查询数据库获得以下数据 
            this._userName = "abc"; 
            this._departmnet = "行政部"; 
            this._phone = "123456"; 
        }
 
        #region 基本属性 
        ///  
        /// 返回验证方式 
        ///  
        public string AuthenticationType 
        { 
            get { return "Form"; } 
        }
 
        ///  
        /// 是否验证 
        ///  
        public bool IsAuthenticated 
        { 
            get { return true; } 
        }
 
        ///  
        /// 返回用户 
        ///  
        public string Name 
        { 
            get { return _userName; } 
        } 
        #endregion 
    }
 
 
    /// 
 
    /// 当前用户安全上下文信息
 
    /// 
 
    public class MyPrincipal:IPrincipal 
    { 
        #region 属性 
        private IIdentity _identity;//用户标识 
        private ArrayList _permissionList;//权限列表 
        #endregion
  
        ///  
        /// 返回用户权限列表 
        ///  
        public ArrayList PermissionList 
        { 
            get { return _permissionList; } 
        }
  
        ///  
        /// 获取当前用户标识 
        ///  
        public IIdentity Identity 
        { 
            get { return _identity; } 
        }
 
        ///  
        /// 当前用户是否指定角色(采用权限值方式,此处返回false) 
        ///  
        ///  
        ///  
        public bool IsInRole(string role) 
        { 
            return false;//返回false 
        }
 
        ///  
        /// 构造函数,用户名构造 
        ///  
        ///  
        public MyPrincipal(string UserName) 
        { 
            _identity = new MyIdentity(UserName); 
            //以下权限根据UserName获取数据库用户拥有的权限值,此次省略 
            _permissionList = new ArrayList(); 
            _permissionList.Add(1); 
            _permissionList.Add(2); 
            _permissionList.Add(3); 
            _permissionList.Add(4); 
            _permissionList.Add(5); 
        }
 
        ///  
        /// 构造函数,用户ID构造 
        ///  
        ///  
        public MyPrincipal(int UserID) 
        { 
            _identity = new MyIdentity(UserID); 
            //以下权限根据UserName获取数据库用户拥有的权限值,此次省略 
            _permissionList = new ArrayList(); 
            _permissionList.Add(1); 
            _permissionList.Add(2); 
            _permissionList.Add(3); 
            _permissionList.Add(4); 
            _permissionList.Add(5); 
        }
 
        ///  
        /// 判断用户是否拥有某权限 
        ///  
        ///  
        ///  
        public bool 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模式下,使用方式: 
首先,我们先做一个权限验证基类!
///  
///权限验证基类 
///  
public class BasePaper:System.Web.UI.Page 
{ 
    public BasePaper() 
       { 
              // 
              //TODO: 在此处添加构造函数逻辑 
              // 
       }
 
    protected override void OnInit(EventArgs e) 
    { 
        BasePage_Load(); 
    }
 
    ///  
    /// 设置权限,默认值为0 
    ///  
    public virtual int PermissionID 
    { 
        get { return 0; } 
    }
 
    ///  
    /// 验证方法 
    ///  
    ///  
    ///  
    private void BasePage_Load() 
    { 
        //权限检查 
        #region 权限检查 
        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(""); 
            Response.End(); 
        } 
        #endregion 
    } 
}
 

OK,到了验证页的时候了。
public partial class ascx_Add :BasePage 
{ 
    public override int PermissionID 
    { 
        get 
        { 
            return 13;//返回要验证权限值 
        } 
    }
 
    protected void Page_Load(object sender, EventArgs e) 
    { 
        // 
    } 
}
 
事实上,在Asp.net MVC模式,更容易对权限进行控制,可以进行更多的细化,对每个动作进行控制。 
MVC模式下: 
首先,先实现一个权限验证基类:
    ///  
    /// 权限验证基类 
    /// 2011.7.3 
    ///  
    public class BasePage : AuthorizeAttribute 
    { 
        ///  
        /// 权限值 
        ///  
        private int _permissionID = 0;
 
        ///         /// 权限值
        ///  
        public int PermissionID 
        { 
            get { return _permissionID; } 
            set { _permissionID = value; } 
        }
 
        ///  
        /// 在过程请求授权时调用。  
        ///  
        /// 对象包括控制器、HTTP 上下文、请求上下文、操作结果和路由数据。 
        public override void 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("");
 
                    HttpContext.Current.Response.End();
 
                    filterContext.Result = new EmptyResult(); 
                } 
            } 
            else 
            { 
                FormsAuthentication.SignOut(); 
                HttpContext.Current.Response.Clear(); 
                HttpContext.Current.Response.Write(""); 
                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) {%> 
    "submit" name="button" id="button" value="删除" /> 
    <%} %>
 

至此,如何实现自定义Identity和Principal,进行整合更多用户信息,和权限验证。
2,通过HttpMoudle注册来实现角色权限控制。继承接口和上面一样
创建一个User类实现IIdentity接口 重写相应的方法
public class User : IIdentity
    {
        private int _id;
        private string _userName;
        private string _password;
        private bool _isAuthenticated;
        #region properties
        public virtual int Id
        {
            get { return this._id; }
            set { this._id = value; }
        }
        public virtual string UserName
        {
            get { return this._userName; }
            set { this._userName = value; }
        }
        public virtual string Password
        {
            get { return this._password; }
            set { this._password = value; }
        }
        //是否通过认证
        public virtual bool IsAuthenticated
        {
            get { return this._isAuthenticated; }
            set { this._isAuthenticated = value; }
        }
        //重写为用户ID
        public virtual string Name
        {
            get
            {
                if (this._isAuthenticated)
                    return this._id.ToString();
                else
                    return "";
            }
        }
        public virtual string AuthenticationType
        {
            get { return "CuyahogaAuthentication"; }
        }
        public User()
        {
            this._id = -1;
            this._isAuthenticated = false;
        }
    }
创建一个CuyahogaPrincipal类实现IPrincipal接口
public class CuyahogaPrincipal : IPrincipal
    {
        private User _user;
        // 返回一个现实IIdentity接口的user对象
        public IIdentity Identity
        {
            get { return this._user; }
        }
        // 当前用户是否属于指定角色 在以后的权限认证中可以使用 也可以使用User类中的相关方法来代替
        public bool IsInRole(string role)
        {
            foreach (Role roleObject in this._user.Roles)
            {
                if (roleObject.Name.Equals(role))
                    return true;
            }
            return false;
        }
        ///初始化 若user通过授权则创建
        public CuyahogaPrincipal(User user)
        {
            if (user != null && user.IsAuthenticated)
            {
                this._user = user;
            }
            else
            {
                throw new SecurityException("Cannot create a principal without u valid user");
            }
        }
    }
创建一个实现IHttpModule的AuthenticationModule类
public class AuthenticationModule : IHttpModule
    {
        private const int AUTHENTICATION_TIMEOUT = 20;
 
        public AuthenticationModule()
        {
        }
 
        public void Init(HttpApplication context)
        {
            context.AuthenticateRequest += new EventHandler(Context_AuthenticateRequest);
        }
 
        public void Dispose()
        {
            // Nothing here    
        }
 
        //登录时 验证用户时使用
        public bool 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);
                    return true;
                }
                else
                {
                    //log.Warn(String.Format("Invalid username-password combination: {0}:{1}.", username, password));
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Unable to log in user '{0}': " + ex.Message, username), ex);
            }
        }
 
        /// 
        /// Log out the current user.注销用户
        /// 
        public void Logout()
        {
            if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
            {
                FormsAuthentication.SignOut();
            }
        }
 
        private void 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包含更多的信息
            }
        }
    }
登录时
protected void 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
                    {
                        //认证失败
                    }
                }
                {
                }
            }
        }
退出登录用
protected void btnLogout_Click(object sender, System.EventArgs e)
        {
            AuthenticationModule am = (AuthenticationModule)Context.ApplicationInstance.Modules["AuthenticationModule"];
            am.Logout();
            Context.Response.Redirect(Context.Request.RawUrl);
        }
这样就实现了身份认证功能

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

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

你可能感兴趣的:(.net使用IIdentity和IPrincipal实现自定义身份及权限认证)