ASP.Net MVC 声明授权和身份验证

ASP.Net MVC claims authorization and authentication

请帮我决定如何为我的项目做授权。

该项目是用 ASP.Net MVC 编写的,是一个允许用户通过 Active Directory 登录的 Intranet 应用程序。

用户可以是初级讲师、高级讲师、HOD 或超级用户。这对于角色来说很容易,但情况比这更复杂,因为这些角色基于您正在查看的任何信息。例如,初级讲师只能看到他讲课的学生的信息等

据我所知,这就是声明的来源。我应该将模块或学生分配给用户。

但是这个过程会变得更加复杂,因为在任何一个地方都没有 AD 用户名及其 students/modules 的列表。

我需要能够检查多个数据库以确定是否应允许用户查看信息。

但有时,有权查看某些信息的用户不会通过任何这些检查。因此,我将不得不使用 AD 用户名、他们的角色和他们的 subjects/students.

创建一个数据库

所以我的问题实际上是关于授权的。我是否可以对索赔进行那种级别的控制?我将如何分配和检查它们?

如果不可能 - 我将如何进行授权?

在每个 Controller 中的每个 Action 的开头都有一个 if 语句感觉不对 - 但这是我的同事所能想到的。

'if' 语句是错误的,它会花费你很长的迭代时间和大量的内存滥用。

基本上,您几乎可以使用 authorize 属性控制每个级别的授权。

但是,您确实需要一个精心打造的实体才能这样做,以免迷失所有规则。强烈建议您在执行此操作之前对您的授权方案有一个适当的计划。

你可以尝试使用switch语句来代替,这在实践中会好很多。

请注意:

Authorization Article 这可能有助于您理解。

如果您创建一个继承自 AuthorizeAttribute 的 class,那么您可以自由地执行您认为合适的任何复杂授权过程。请参阅我的回答 here,了解如何操作。

这是我用来查询和缓存 AD 角色的一些代码:

private static Dictionary<Tuple<string, string>, bool> groupIdentityCache = new Dictionary<Tuple<string, string>, bool>();

..

public static bool UserHasRole(IIdentity identity, string groupShortName)     
{
    // (we rename our actual AD roles to shorter ones relevant to the site
    // e.g. [MyAuthorizeAttribute(Roles = "Support,Admin")])
    if (!AdLongGroupNames.ContainsKey(groupShortName.ToUpper())) return false;
    string fullADGroupName = AdLongGroupNames[groupShortName.ToUpper()];            
    Tuple<string, string> key = new Tuple<string, string>(identity.Name.ToUpper(), groupShortName.ToUpper());
    if (!groupIdentityCache.ContainsKey(key))
    {
        using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "DOMAINNAME"))      
        {
            using (GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, fullADGroupName))
            {
                using (UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, GetLogin(identity)))
                {
                    groupIdentityCache[key] = userPrincipal.IsMemberOf(groupPrincipal);
                }
            }
        }                
    }            
    return groupIdentityCache[key];
}

public static string GetLogin(IIdentity identity)
{
    string[] parts = identity.Name.Split('\');
    if (parts.Count() < 2) return parts[0]; else return parts[1];
}

如果您缓存角色成员资格,您还必须在 Session_Start 上清除缓存以使更改生效。

您可以通过添加到 groupIdentityCache 字典来修改此解决方案以包括来自非 AD 源(例如 class 成员资格的数据库等)的角色。修改groupIdentityCache也可以在测试时提供帮助。