Asp.net mvc Asp.net MVC允许用户在角色之间切换

Asp.net mvc Asp.net MVC允许用户在角色之间切换,asp.net-mvc,forms-authentication,global-asax,asp.net-roles,Asp.net Mvc,Forms Authentication,Global Asax,Asp.net Roles,我正在开发一个复杂的网站,用户有多种角色。用户还与数据库中的其他项目相关联,这些项目及其角色将定义他们在网站上可以看到和做什么 现在,一些用户拥有多个角色,但由于结构复杂,网站一次只能处理一个角色 这个想法是,用户登录后,在网站的一角有一个下拉列表,可以选择自己的角色之一。如果他只有一个角色,则没有下拉列表 现在,我将上次选择的角色值与用户的其他设置一起存储在数据库中。当他回来时,这个角色仍然被记住 整个网站都应该可以访问下拉列表的值。 我想做两件事: 将当前角色存储在会话中 重写IsInRol

我正在开发一个复杂的网站,用户有多种角色。用户还与数据库中的其他项目相关联,这些项目及其角色将定义他们在网站上可以看到和做什么

现在,一些用户拥有多个角色,但由于结构复杂,网站一次只能处理一个角色

这个想法是,用户登录后,在网站的一角有一个下拉列表,可以选择自己的角色之一。如果他只有一个角色,则没有下拉列表

现在,我将上次选择的角色值与用户的其他设置一起存储在数据库中。当他回来时,这个角色仍然被记住

整个网站都应该可以访问下拉列表的值。 我想做两件事:

  • 将当前角色存储在
    会话中
  • 重写
    IsInRole
    方法或编写
    IsCurrentlyInRole
    方法,以检查对当前选定角色的所有访问,而不是所有角色,就像原始
    IsInRole
    方法一样
  • 对于会话中的存储部分,我认为最好在
    Global.asax中这样做

        protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
            if (User != null && User.Identity.IsAuthenticated) {
                //check for roles session.
                if (Session["CurrentRole"] == null) {
                    NASDataContext _db = new NASDataContext();
                    var userparams = _db.aspnet_Users.First(q => q.LoweredUserName == User.Identity.Name).UserParam;
                    if (userparams.US_HuidigeRol.HasValue) {
                        var role = userparams.aspnet_Role;
                        if (User.IsInRole(role.LoweredRoleName)) {
                            //safe
                            Session["CurrentRole"] = role.LoweredRoleName;
                        } else {
                            userparams.US_HuidigeRol = null;
                            _db.SubmitChanges();
                        }
                    } else {
                        //no value
                        //check amount of roles
                        string[] roles = Roles.GetRolesForUser(userparams.aspnet_User.UserName);
                        if (roles.Length > 0) {
                            var role = _db.aspnet_Roles.First(q => q.LoweredRoleName == roles[0].ToLower());
                            userparams.US_HuidigeRol = role.RoleId;
                            Session["CurrentRole"] = role.LoweredRoleName;
                        }
                    }
                }
    
            }
        }
    
    但显然这会导致运行时错误<代码>会话状态在此上下文中不可用。

  • 我该如何解决这个问题,这是吗 真的是放这个的最好地方 密码
  • 如何使用
    iscurrentlyinlole
    扩展用户(
    IPrincipal
    ?),而不丢失所有其他功能
  • 也许我做错了,还有更好的方法吗

  • 非常感谢您的帮助

    如果您确实希望用户一次只拥有一个活动角色(这意味着您希望覆盖IsInRole),那么将用户的所有“潜在”角色存储在一个单独的位置可能是最容易的,但实际上一次只允许他们处于一个ASP.NET身份验证角色中。当他们选择新角色时,使用内置方法将其从当前角色中删除并添加到新角色。

    是的,您无法访问应用程序\u AuthenticateRequest中的会话。
    我已经创建了自己的CustomPrincipal。我将向您展示我最近所做的一个示例:

    public class CustomPrincipal: IPrincipal
    {
        public CustomPrincipal(IIdentity identity, string[] roles, string ActiveRole)
        {
            this.Identity = identity;
            this.Roles = roles;
            this.Code = code;
        }
    
        public IIdentity Identity
        {
            get;
            private set;
        }
    
        public string ActiveRole
        {
            get;
            private set;
        }
    
        public string[] Roles
        {
            get;
            private set;
        }
    
        public string ExtendedName { get; set; }
    
        // you can add your IsCurrentlyInRole 
    
        public bool IsInRole(string role)
        {
            return (Array.BinarySearch(this.Roles, role) >= 0 ? true : false);  
        }
    }
    
    如果有身份验证票证(用户已登录),我的应用程序_AuthenticateRequest将读取cookie:

    我已经扩展了cookie,添加了身份验证票证的用户数据。我在这里添加了额外信息:

    这是在登录后创建cookie的函数:

        public static bool Create(string Username, bool Persistent, HttpContext currentContext, string ActiveRole , string[] Groups)
        {
            string userData = "";
    
            // You can store your infos
            userData = ActiveRole + "#" string.Join("|", Groups);
    
            FormsAuthenticationTicket authTicket =
                new FormsAuthenticationTicket(
                1,                                                                // version
                Username,
                DateTime.Now,                                                     // creation
                DateTime.Now.AddMinutes(My.Application.COOKIE_PERSISTENCE),       // Expiration 
                Persistent,                                                       // Persistent
                userData);                                                        // Additional informations
    
            string encryptedTicket = System.Web.Security.FormsAuthentication.Encrypt(authTicket);
    
            HttpCookie authCookie = new HttpCookie(My.Application.FORMS_COOKIE_NAME, encryptedTicket);
    
            if (Persistent)
            {
                authCookie.Expires = authTicket.Expiration;
                authCookie.Path = FormsAuthentication.FormsCookiePath;
            }
    
            currentContext.Response.Cookies.Add(authCookie);
    
            return (true);
        }
    
    现在,您可以在应用程序中的任何位置访问您的信息:

    CustomPrincipal currentPrincipal = (CustomPrincipal)HttpContext.User;
    
    因此,您可以访问自定义主体成员:currentPrincipal.ActiveRole

    当用户更改其角色(活动角色)时,您可以重写cookie

    我忘了说我在authTicket.UserData中存储了一个JSON序列化类,因此反序列化和解析很容易


    你可以找到更多有趣的开箱思考信息。虽然它让我担心我需要为管理面板中的用户添加和管理角色而编写的所有其他额外代码…非常有趣!我用sessions和其他方法修复了它,但是我可能会使用部分代码来改进它。我还覆盖了
    authorized属性
    会话往往会很快失去它的值,这使得我需要每次检查它并经常重新加载它。我将发布我的最终代码,以便您可以很快查看。经过几天的努力,我最近实现了我的解决方案。它现在运行得非常好。如果您需要帮助,请询问我。我在
    IPrincipal
    上使用扩展方法实现了这一点。但想法非常相似。:)
    CustomPrincipal currentPrincipal = (CustomPrincipal)HttpContext.User;