【问题标题】:How to use Roles with Integrated Windows Authentication如何使用具有集成 Windows 身份验证的角色
【发布时间】:2015-12-29 13:22:20
【问题描述】:

我正在开发一个在 ASP.NET MVC 5 中使用 Web API 2 实现的 Web 应用程序。

我通过将以下代码添加到 web.config 来实现集成 Windows 身份验证:

<system.web>
  <authentication mode="Windows" />
</system.web>
<system.webServer>
  <security>
    <authentication>
      <windowsAuthentication enabled="true"/>
    </authentication>
  </security>
</system.webServer>

并通过在我的控制器顶部添加 [Authorize] 注释。

现在,我被要求根据用户的角色授予对某些功能的访问权限。我有一张表,我在其中保存用户权限,但我不知道如何创建这些角色,并将正确的权限与它们相关联。

任何帮助将不胜感激。

提前致谢

[更新]

根据梅森的回答,我稍微更新了代码。

在 web.config 中添加了以下行:

<roleManager defaultProvider="MyRoleProvider">
  <providers>
    <add
        name="MyRoleProvider"
        type="MyApp.App_Start.MyRoleProvider"
        applicationName="My Tool" />
  </providers>
</roleManager>

MyRoleProvider.cs:

public class MyRoleProvider : RoleProvider
{
    private MyEntities db = new MyEntities();

    public override void AddUsersToRoles(string[] usernames, string[] roleNames)
    {
        throw new NotImplementedException();
    }

    public override string ApplicationName
    {
        get;
        set;
    }

    public override void CreateRole(string roleName)
    {
        throw new NotImplementedException();
    }

    public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
    {
        throw new NotImplementedException();
    }

    public override string[] FindUsersInRole(string roleName, string usernameToMatch)
    {
        throw new NotImplementedException();
    }

    public override string[] GetAllRoles()
    {
        throw new NotImplementedException();
    }

    public override string[] GetRolesForUser(string username)
    {
        throw new NotImplementedException();
    }

    public override string[] GetUsersInRole(string roleName)
    {
        throw new NotImplementedException();
    }

    public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
    {
        throw new NotImplementedException();
    }

    public override bool IsUserInRole(string username, string roleName)
    {
        vUser user = db.vUsers.Where(u => u.UserName == username).First();
        if (roleName == "User")
        {
            if (user.IsAllowedToView == true)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else if (roleName == "Administrator")
        {
            if (user.IsAllowedToSubmit == true)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    public override bool RoleExists(string roleName)
    {
        if (roleName == "User" || roleName == "Administrator")
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

当我在控制器上使用[Authorize] 注释并调用HttpContext.Current.User.Identity.Name 时,它会返回我用来登录我的机器的ID。 (AD 的一部分)但是,如果我使用 [Authorize(Roles="User")],它会一次又一次地询问我的用户名和密码,并且不接受任何内容。我在 MyRoleProvider 类的每个方法上都设置了断点,但程序并没有停止,这让我觉得它可能甚至没有调用提供程序。

【问题讨论】:

  • 查看我的回答here。您只需要继承一个类,连接方法以从表中提取适当的数据,然后您就可以开始在您的应用程序中使用这些角色。
  • @mason 感谢您将我引导至该帖子。我已经实现了角色管理器,并添加到我的 web.config 中。我现在的问题是如何将用户 ID 传递给角色管理器。我在控制器顶部有[Authorize(Roles="User")],但它不允许我查看它。如何将用户名参数传递给 public override bool IsUserInRole(string username, string roleName) ?
  • 你不需要。当我们像我在回答中显示的那样在 web.config 中注册我们的角色管理器时,系统会意识到它。如果您查看该Authorize 属性的源代码,您会看到它代表您调用已注册的角色管理器(如果您想验证,请在角色管理器中设置断点)。因此,您无需手动获取用户名并将其传递给角色管理器。但是,如果您出于其他原因确实需要用户名,则来自 HttpContext.Current.User.Identity.Name
  • @mason 感谢您的回复。当我打印 HttpContext.Current.User.Identity.Name 时,我可以看到我的用户 ID,但是当我使用 [Authorize(Roles="User")] 注释时,它一直在询问我的用户名和密码,并且它不接受我使用的用户名和密码登录到 Windows。我还在 MyRoleProvider 类中设置了一些断点,但看起来它甚至没有被调用。我只实现了 IsUserInRole() 和 RoleExists() 方法。我是否需要实现一些其他的才能让它工作?
  • 您可以通过在角色管理器的其他方法中设置断点并查看它们是否被命中来判断。但是如果你直接复制了我的代码,那么当这些代码被命中时你应该得到NotImplementedException。所以这让我认为它甚至没有到达角色经理。更新您的问题,显示您如何在 web.config 中注册角色管理器,并显示您的角色管理器代码。该网站是否托管在属于 Active Directory 一部分的服务器上,与您的客户端 PC 所在的服务器相同?

标签: asp.net asp.net-mvc asp.net-mvc-5 asp.net-web-api2 windows-authentication


【解决方案1】:

在每个控制器甚至控制器内的每个方法上,您都可以添加自己的自定义授权角色。

    [Authorize(Roles="Admin,Doctor")]
    public class Investigation : Controller
    {

    }

注意: 角色的编写方式必须与插入数据库的方式相同。(区分大小写)

【讨论】:

    【解决方案2】:

    如果您希望从 Active Directory 管理角色,您始终可以为每个特定角色创建 Active Directory 用户组,然后在控制器顶部使用 [Authorize(Roles="{AD_GROUP_NAME}")] 注释。

    【讨论】:

    • 这需要你是域管理员,或者有域管理员的配合。虽然它适用于某些情况,但它绝对不适用于所有情况,特别是不适用于这种情况,因为他已经有一个包含该信息的数据库。
    • 同意。只是提供一个可能的替代方案。
    【解决方案3】:

    在您的特定情况下(基于聊天),听起来基于角色的概念不适合您,因为您的权限存储在用户级别而不是角色级别,并且您无法更改方式由于公司的限制,这有效。

    相反,您应该 write your own filter 将其应用于您的操作方法。该过滤器可能应该实现IAuthorizationFilter。这将允许您执行以下操作:

    [RequirePermissions("Save")]
    public ActionResult Save(Data date)
    {
        Database.Save(data);
        return View("Success");
    }
    

    可能验证用户是否具有该权限的逻辑应该抽象到一个公共类中,以便您也可以在视图中重用该逻辑。

    【讨论】:

      【解决方案4】:
              public override string[] GetRolesForUser(string username)
              {
                  var userrole = from role in db.roles
                                 where username == role.userID
                                 select role.role1;
                  if (userrole != null)
                      return userrole.ToArray();
                  else
                      return new string[] { };
                  //throw new NotImplementedException();
              }
      

      这个函数应该被编辑。

      【讨论】:

      • 能否请您详细说明您的答案,添加更多关于您提供的解决方案的描述?
      • 我在 MyRoleProvider.cs 中编辑了这个函数,然后它就可以工作了!它运行时我不再需要输入我的用户名和密码了:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 2013-03-15
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 1970-01-01
      • 2014-01-23
      相关资源
      最近更新 更多