表单身份验证User.IsInRole()随机无法在LogOn中工作

时间:2012-08-12 03:39:17

标签: asp.net-mvc-3 forms-authentication

我正在更改MVC3项目中的默认LogOn函数,以使用role将用户重定向到基于User.IsInRole()的某个页面。当我测试这个时,前几个用户按预期重定向,但之后我有一对没有重定向到他们应该的位置(他们通过所有语句并点击默认的主页索引。)似乎完全随机,有时我的admin将被带到管理页面,有时则没有。

我的LogOn功能:

[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",而当它不存在时我就不会这样做。

有人知道为什么即使用户在角色中,User.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()之后的某个时刻,User.IsInRole()会正常工作吗?是在cookie掉线后,还是什么?

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

1 个答案:

答案 0 :(得分:0)

问题是,当调用LogOn函数时,传入请求没有经过身份验证的用户,User对象为null,直到新请求填充User对象为止。因此,当User.IsInRole()中调用LogOn时,Usernull

  

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

     

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

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