ASP.NET MVC和自定义角色的Windows身份验证

15
我正在尝试在我的ASP.NET MVC2应用程序中实现Windows身份验证。 我已经按照官方文档建议的所有步骤进行了操作。
<authentication mode="Windows" />

<authorization>
  <deny users="?" />
</authorization>
我已经指定了NTLM身份验证。到目前为止一切都很好,一切正常工作。 我想检查用户登录并与我的数据库进行对比。我想从我的表中获取角色,然后使用自定义属性管理授权。 我不想使用成员资格和角色提供程序。 因为它们已被用于Internet应用程序(这是内部应用程序),我已经准备好了我的用户/角色表。

在我的Internet应用程序中,我有一个表单,用户输入数据。该表单发布到一个控制器,该控制器检查所有内容并创建一个带有已登录用户的cookie(以及角色)。

在我的 global.asax 中,我捕获了 AuthenticateRequest 事件,在那里读取 cookie 并创建一个自定义主体,我在整个应用程序中使用它来检查授权。

如何使用Windows身份验证实现这一点?

2个回答

23

只需在Global.asax中创建一个新的principal并将其分配给用户和线程,或者使用一个操作筛选器。

protected void Application_AuthenticateRequest(object sender, EventArgs args)
{
  if(HttpContext.Current != null)
  {
     String [] roles = GetRolesFromSomeDataTable(HttpContext.Current.User.Identity.Name);

     GenericPrincipal principal = new GenericPrincipal(HttpContext.Current.User.Identity, roles);

     Thread.CurrentPrincipal = HttpContext.Current.User = principal;
  }
}

如果用户没有匹配的任何角色,可以使用web.config授权元素禁止其访问应用程序:

<authorization>
  <allow roles="blah,whatever"/>
  <deny users="*"/>               
</authorization>

1
修改您的Web配置授权元素以限制用户只能访问特定角色。我将在帖子中提供示例。 - Xhalent
2
由于CAS(代码访问安全)针对的是线程主体,如果您仅更新HttpContext.User,则无法保持同步。这意味着声明性属性(如PrincipalPermission等)将不会根据您预期的主体进行评估。最佳实践是同时更新两者。 - Xhalent
6
抱歉,这可能是一个愚蠢的问题...但这样做不会在每个经过身份验证的请求中查询数据库并重建主体吗?或者我对Application_AuthenticateRequest的触发方式有误解... - nokturnal
1
是的,这会在每个授权请求时调用。它还为当前线程每次创建一个新的主体。一些混合使用Windows和Forms身份验证(cookie)来实现此目的。 - Papa Burgundy
@nokturnal(好名字),我是编程新手,但我正在尝试解决这个问题。这段代码确实可以工作,但似乎执行了很多次,并且我需要调用数据库来获取组,这似乎有些浪费。有什么方法可以改进吗? - Dave Kelly
显示剩余3条评论

6

针对上面的答案,我想补充一点,希望能够帮助一些人节省时间。

我有一个使用VS 2015的Intranet MVC 5站点。

在我的代码中,只有当顶部行更新为HttpContext.Current.User时,它才能正常工作。如果用户尚未在数据库中创建,则该站点会向我返回指向HttpContext.Current.User的空引用。通过在第一行添加“ .User”,可以在首次加载时绕过该代码并使其正常工作。

if (HttpContext.Current.User != null)
        {


            String[] roles = GetRolesFromSomeDataTable(HttpContext.Current.User.Identity.Name);

            GenericPrincipal principal = new GenericPrincipal(HttpContext.Current.User.Identity, roles);

            Thread.CurrentPrincipal = HttpContext.Current.User = principal;
        }

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