• 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

  • 相关阅读:
    Spring Boot 配置文件和命令行配置
    Spring Boot RestApi 测试教程 Mock 的使用
    Spring Boot 集成 Swagger2 教程
    Spring Boot Web 开发@Controller @RestController 使用教程
    SpringBoot RESTful API 架构风格实践
    Spring Boot 使用 Aop 实现日志全局拦截
    Spring Boot 全局异常处理
    Spring Boot Thymeleaf 模板引擎的使用
    Spring Boot Log 日志使用教程
    IDEA 下的 github 创建提交与修改
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/12054791.html
Copyright © 2020-2023  润新知