ASP.NET MVC4身份验证成功但项目构建后缺少角色

时间:2014-02-10 16:22:29

标签: c# asp.net asp.net-mvc asp.net-mvc-4 simplemembership

我搜索过很多SO和其他页面,但仍然找不到类似的案例。

我的应用程序正在使用SimpleMembership。它具有基于角色的用户菜单,大多数操作都是[Authorize(Roles =“aaa,bbb”)]属性。

在应用程序构建或使浏览器闲置一段时间后,用户将从任何单击的链接重定向到登录页面。奇怪的是,登录名仍然有效,但没有附加的角色名称。

在上述情况下,用户可以使用[授权]属性访问操作。我想知道是否有任何我遗漏的内容,或者只要认证有效,我就能保持角色信息的存在?

以下是控制器操作中用于呈现菜单的代码:

    public ActionResult Menu()
    {
        if (Roles.IsUserInRole("Admin"))
        {
            return View("MenuAdmin");
        }
        if (Roles.IsUserInRole("Advising"))
        {
            return View("MenuAdvising");
        }
        if (Roles.IsUserInRole("StudentDevelopment"))
        {
            return View("MenuStudentDevelopment");
        }...

自定义_logonPartial以显示登录名和角色

> @if (Request.IsAuthenticated) {
    <text>
        Logged in: @Html.ActionLink(User.Identity.Name, "Manage", "Account", routeValues: null, htmlAttributes: new { @class = "username", title = "Manage" }) as
        @String.Join(",", Roles.GetRolesForUser(User.Identity.Name))
        @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
            @Html.AntiForgeryToken()
            <a href="javascript:document.getElementById('logoutForm').submit()">Log off</a>
        }
    </text>

1 个答案:

答案 0 :(得分:1)

只要用户已登录,角色信息就可用。在您的情况下,您正在呼叫:

Roles.GetRolesForUser(User.Identity.Name)

获取角色列表。这实际上命中数据库以获取角色,因此只要我们用户名在Identity中可用,它将返回角色,假设用户已分配角色。如果用户身份验证,则用户名应该可用。您正在检查Request.IsAuthenticated。检查User.Identity.IsAuthenticated。

可能更好

有一种方法可以在不使用声明查询数据库的情况下获取角色。一般来说,我不会在视图中放置这样的逻辑和访问系统变量。我会在我的控制器动作中使用这种方法来获得角色。

        var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
        var roles = prinicpal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value);
        ViewBag.Roles = roles;

将您需要的信息放在ViewBag中,或者创建一个传递给View的模型。这种获取角色的方法不需要往返数据库。

更新地址评论

MVC 4的标准AuthorizeAttribute使用配置的成员资格和角色提供程序(在您的情况下为SimpleMembership)来获取角色。它不会假设使用的声明,因此每次都会进入数据库。实际上,它必须两次访问数据库,一次获取登录用户的用户ID,然后根据该用户ID获取角色。不是很有效率。令人惊讶的是,即使您没有将任何角色作为参数传递,它也不会根据角色授权用户并且只需要进行身份验证即可。我用剖析器验证了这一点。

为了提高效率并且不需要访问数据库,您可以编写自定义AuthorizeAttribute以使用声明。 Here is an article that describes how to do this,包含示例源代码的链接。

我无法解释您所描述的情景,这种情况发生在构建之后。但是,如果您创建自定义属性并使用它,您将能够调试并查看到底发生了什么。此外,我不会过分担心它,因为它不应该是您在生产中看到的典型情况。