代码之家  ›  专栏  ›  技术社区  ›  Garrett Fogerlie

窗体身份验证用户.IsInRole()在登录中随机不工作

  •  -2
  • Garrett Fogerlie  · 技术社区  · 13 年前

    我在一个MVC3项目中更改了默认的LogOn函数,以根据用户的 role 通过使用 User.IsInRole() 。当我测试这一点时,前几位用户按预期进行了重定向,但在那之后,我有几位用户没有重定向到他们应该重定向的地方(他们通过了所有的语句并点击了默认的主页索引)。这似乎完全是随机的,有时我 admin 会被带到管理页面,其他时候不会。

    我的登录功能:

    [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        if(ModelState.IsValid)
        {
            if(Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                if(Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && 
                    returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && 
                    !returnUrl.StartsWith("/\\"))
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    if(User.IsInRole("Admin") || User.IsInRole("SuperAdmin"))
                    {
                        return RedirectToAction("Index", "Admin");
                    }
                    else if(User.IsInRole("Employee"))
                    {
                        return RedirectToAction("Index", "Employee");
                    }
                    else if(User.IsInRole("Accounting"))
                    {
                        return RedirectToAction("Index", "Accounting");
                    }
                    // If the user is in none of those roles, send them to the home index
                    return RedirectToAction("Index", "Home");
                }
            }
            else
            {
                MembershipUser user = Membership.GetUser(model.UserName);
                if(user == null)
                    ModelState.AddModelError("", "The user name or password provided is incorrect.");
                else
                    ModelState.AddModelError("", "You haven't been approved yet, or you are locked out.");
            }
        }
        // If we got this far, something failed, redisplay form
        return View(model);
    }
    

    看看IntelliTrace,有时它似乎不需要查询数据库,例如,当它工作时,我看到 Execute Reader "dbo.aspnet_UsersInRoles_GetRolesForUser" 如果没有,我就不会。

    有人知道为什么吗 用户.IsInRole() 即使用户处于该角色,也会返回false吗?是否存在某种形式的兑现,为什么不每次都对数据库进行查询?

    我确信用户处于我测试的角色中,我知道它没有试图重定向到返回url,我也知道角色没有存储在任何cookie中。任何想法都将不胜感激,我相信我可以用另一种方式来解决这个问题,但现在我更感兴趣的是为什么这种简单的方法不起作用。

    使现代化

    我发现如果我更换 If(User.IsInRole(... 语句重定向到另一个叫做排序的操作,我在那里添加if语句,它100%有效。

    public ActionResult Sorting()
    {
        if(User.IsInRole("Admin") || User.IsInRole("SuperAdmin"))
        {
            return RedirectToAction("Index", "Admin");
        }
        else if(User.IsInRole("Employee"))
        {
            return RedirectToAction("Index", "Employee");
        }
        else if(User.IsInRole("Accounting"))
        {
            return RedirectToAction("Index", "Accounting");
        }
        // If the user is in none of those roles, send them to the home index
        return RedirectToAction("Index", "Home");
    }
    

    很明显 User.Identity.Name 直到 LogOn 函数退出。这是正确的吗?我想在 Membership.ValidateUser 被调用时,用户已通过身份验证,显然没有。

    那么在什么时候 Membership.ValidateUser() 被调用时 用户.IsInRole() 是否能正常工作?是在饼干掉下来之后,还是什么?

    我想我可以用 if(Roles.IsUserInRole(model.UserName, "Admin")) 因为我确实提交了模型中的用户名。你认为这是一个更好的主意还是只使用 Sorting 像我一样重定向?

    1 回复  |  直到 13 年前
        1
  •  0
  •   Garrett Fogerlie    13 年前

    问题是当 LogOn 函数,传入的请求没有经过身份验证的用户,user对象为null,直到发出新的请求,才填充user对象。所以什么时候 User.IsInRole() 在中调用 登录 , User null

    简而言之,User对象是在ASP.NET管道中较早设置的,长 在执行请求的ASP.NET页的代码之前。现在,在 随后访问,ASP.NET运行时将看到表单 身份验证票证和User.Identity.IsAuthenticated将为true, 但不是应此请求。
    。。。

    此外,您将无法获得用户名 来自User.Identity.Name。请改用LoginControlID.Username。

    http://forums.asp.net/post/1988606.aspx