-2

我正在更改 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",而当它不工作时我没有。

有谁知道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像我一样使用重定向?

4

1 回答 1

0

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

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

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

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

于 2012-08-12T05:51:53.500 回答