首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Asp.net MVC让用户在角色之间切换

Asp.net MVC让用户在角色之间切换
EN

Stack Overflow用户
提问于 2011-02-17 14:29:37
回答 2查看 2.3K关注 0票数 2

我正在开发一个复杂的网站,用户有多个角色。用户还耦合在DB中的其他项目上,这些项目连同他们的角色将定义他们可以在网站上看到和做什么。

目前,一些用户有一个以上的角色,但由于其复杂的结构,网站一次只能处理一个角色。

这个想法是一个用户登录并在网站的角落有一个下拉列表,在那里他可以选择他的角色之一。如果他只有一个角色,就没有下降权。

现在,我将最后选择的角色值与他的其他设置一起存储在DB中。当他回来的时候,这样的角色仍然被记住。

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

  1. 将当前角色存储在Session中。
  2. 重写IsInRole方法或编写IsCurrentlyInRole方法以检查对当前选定角色的所有访问,而不是所有角色,原始的IsInRole方法也是如此

对于会话存储部分,我认为在Global.asax中这样做会更好

代码语言:javascript
复制
    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;
                    }
                }
            }

        }
    }

但显然这会产生运行时错误。Session state is not available in this context.

  1. 我如何解决这个问题,这真的是放置这些代码的最佳地方吗?
  2. 如何扩展用户(IPrincipal?)在没有失去所有其他功能的情况下使用IsCurrentlyInRole
  3. 也许我做错了而且有更好的方法来做这件事?

任何帮助都是非常感谢的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-18 13:02:32

是的,您不能访问Application_AuthenticateRequest中的会话。

我已经创建了自己的CustomPrincipal。我将向你们展示我最近所做的事情:

代码语言:javascript
复制
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);  
    }
}

如果存在身份验证票证(用户已登录),我的Application_AuthenticateRequest将读取cookie:

代码语言:javascript
复制
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[My.Application.FORMS_COOKIE_NAME];
    if ((authCookie != null) && (authCookie.Value != null))
    {
        Context.User = Cookie.GetPrincipal(authCookie);
    }
}


public class Cookie
    {
    public static IPrincipal GetPrincipal(HttpCookie authCookie)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        if (authTicket != null)
        {
            string ActiveRole = "";
            string[] Roles = { "" };
            if ((authTicket.UserData != null) && (!String.IsNullOrEmpty(authTicket.UserData)))
            {
            // you have to parse the string and get the ActiveRole and Roles.
            ActiveRole = authTicket.UserData.ToString();
            Roles = authTicket.UserData.ToString();
            }
            var identity = new GenericIdentity(authTicket.Name, "FormAuthentication");
            var principal = new CustomPrincipal(identity, Roles, ActiveRole );
            principal.ExtendedName = ExtendedName;
            return (principal);
        }
        return (null);
    }
 }

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

这是在loging之后创建cookie的函数:

代码语言:javascript
复制
    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);
    }

现在,您可以在应用程序中的任何地方访问您的信息:

代码语言:javascript
复制
CustomPrincipal currentPrincipal = (CustomPrincipal)HttpContext.User;

这样您就可以访问您的自定义主体成员: currentPrincipal.ActiveRole

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

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

您可以找到更多的信息这里

票数 3
EN

Stack Overflow用户

发布于 2011-02-17 15:12:23

如果您真的希望用户一次只拥有一个活动角色(就像想要覆盖IsInRole所暗示的那样),那么也许将用户的所有“潜在”角色存储在一个单独的位置是最简单的,但实际上只允许它们一次处于一个ASP.NET身份验证角色中。当他们选择一个新角色时,使用内置方法将其从当前角色中删除并添加到新角色中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5030227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档