我该如何根据角色更改ASP.Net MVC登录重定向?

7

我在我的MVC项目的Account Controller中输入了以下代码,我同时拥有管理员和经理角色。当我登录时,我被重定向回到我的主页索引而不是被重定向到我的AdminApp索引。你有什么想法,我在代码中哪里出错了吗?

[AcceptVerbs(HttpVerbs.Post)]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
        Justification = "Needs to take same parameter type as Controller.Redirect()")]
    public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
    {

        if (!ValidateLogOn(userName, password))
        {
                return View();
        }

        FormsAuth.SignIn(userName, rememberMe);
        if (!String.IsNullOrEmpty(returnUrl))
        {
            return Redirect(returnUrl);
        }
        else
        {
            if (User.IsInRole("Administrator") || (User.IsInRole("Manager")))
            {
                return RedirectToAction("Index", "AdminApp");
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }

        }
    } 
3个回答

20
你的代码未按预期工作是因为用户尚未登录和进行身份验证。说什么?但你确实调用了SignIn!
FormsAuth.SignIn(userName, rememberMe) - 在这种情况下只是FormsAuthentication.SetAuthCookie(userName,createPersistentCookie)的一个包装器 - 仅在响应的一部分中将asp.net授权cookie设置到用户浏览器上。只有在此后的请求中,用户浏览器才会拥有cookie,从而导致asp.net成员资格正确设置“User”对象。 LogOn方法中的所有代码仍然假定为匿名用户,因此您的IsInRole检查失败并且被重定向到主页。将if语句放在另一页并在登录后,您将看到现在User.IsInRole按预期工作。(实际上,这就是您使用User.IsInRole的方法,只是不在登录过程中)
那么如何在实际的登录过程中检查呢?Roles.IsUserInRoleRoles.GetRolesForUser是一些方法,例如:
if (Roles.IsUserInRole(userName, "Administrator") || Roles.IsUserInRole(userName, "Administrator"))
{
    return RedirectToAction("Index", "AdminApp");
}

您必须明确指定登录用户的用户名,这实际上将执行一次针对成员数据存储的查询。就此而言,我相信上面的代码会导致执行两个查询,这可能不是最理想的。这就是Roles.GetRolesForUser可能是更好选择的原因:

string[] roles = Roles.GetRolesForUser(userName);
if (roles.Contains("Administrator") || roles.Contains("Manager"))
{
    return RedirectToAction("Index", "AdminApp");
}

希望能对你有所帮助!


2

我正在使用VS 2013和它的新身份验证模型,最终选择了以下方案:

foreach (IdentityUserRole identityUserRole in user.Roles)
{
   if (identityUserRole.RoleId == "AdminRoleId")
   {
     return RedirectToAction("Index", "Admin");
   }
   else if (identityUserRole.RoleId == "MemberRoleId")
   {
     return RedirectToAction("Index", "Members");
   }
 }

0

你需要取消if语句的嵌套。请按以下方式进行修改:

将此处更改为:

FormsAuth.SignIn(userName, rememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{            
    return Redirect(returnUrl);
}        
else
{ 
    if (User.IsInRole("Administrator") || (User.IsInRole("Manager")))
    {               
        return RedirectToAction("Index", "AdminApp");     
    } 
    else          
    {                
    return RedirectToAction("Index", "Home"); 
    }     
}

转换为:

if (User.IsInRole("Administrator") || (User.IsInRole("Manager")))
{               
    return RedirectToAction("Index", "AdminApp");     
} 
else          
{                
return RedirectToAction("Index", "Home"); 
}     

问题在于行 if(!String.IsNullOrEmpty(returnUrl))) 的评估结果为True,因为returnUrl参数默认具有您来自的页面的URL。

嗯,我尝试过但对我没用。我可以在aspx页面上成功使用User.InInRole来显示/隐藏链接,但当我将其放在控制器中时它不起作用。在控制器中还有其他方法可以执行此操作吗? - Ben
不应该有太大区别,但你可以尝试使用Roles.IsUserInRole()方法。然而,我认为这是与User.IsInRole()方法最终调用的相同方法。 - Jeff French

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接