ASP.NET安全性:角色名称的单个条目

本文关键字:单个条 角色 NET 安全性 ASP | 更新日期: 2023-09-27 18:20:48

我们正在构建一个ASP.NET应用程序,并要求使用公司LDAP系统(Siteminder)进行身份验证(好处是:没有登录对话框)。角色是在LDAP工具中创建的,用户由userland管理员分配给这些角色(请阅读:结构必须易于理解)。目前,所有使用该系统的应用程序都使用双重输入过程,即将应用程序中标识的角色手动输入LDAP系统并分配用户,然后在基于应用程序的控制面板中将应用程序功能分配给其角色镜像。这是可行的,但需要双重输入,这让我很困扰。

我想实现的是,应用程序查询LDAP系统,以获得分配给应用程序的角色列表(在LDAP系统中标识),并用它们填充角色:功能控制面板。这部分看起来很简单。然而,当我弄清楚在Authorize属性中放什么时,我就不清楚了:

[Authorize(Roles = "Admin, Moderator")]

会变成。。。什么

[Authorize(LoadedRoles(r => r.FindAll("some expression that describes the roles that have a particular permission")))]

我真的很喜欢这里的蓝天。我读过这个问题,从体系结构的角度来看,我喜欢这个建议将权限作为角色的答案。但对于需要管理用户的用户管理者来说,这可能是不可接受的。另一方面,这个问题将事物转化为非字符串资源,但我无法想象如何将其转化为"包含这种功能的角色"。

有什么建议吗?

更新:

根据下面@venerik的建议,我已经取得了一些进展。目前,我正在将所有内容封装在[AuthorizeFunctionAttribute]中,稍后将把各个片段农场到它们所属的位置。为此,我创建了三个变量:

    private IList<KeyValuePair<long, string>> Roles;
    private IList<KeyValuePair<long, string>> Functions;
    private IList<RoleFunction> RoleFunctions;

然后将静态数据放入其中:

Roles = new ICollection<KeyValuePair<long, string>>();
Roles.Add(KeyValuePair<long, string>(1, "Basic User"));
Roles.Add(KeyValuePair<long, string>(2, "Administrator"));
Functions = new ICollection<KeyValuePair<long, string>>();
Functions.Add(KeyValuePair<long,string>(1,"List Things"));
Functions.Add(KeyValuePair<long,string>(2,"Add Or Edit Things"));
Functions.Add(KeyValuePair<long,string>(3,"Delete Things"));

并最终将它们结合在一起(以一种复杂的方式为未来奠定基础):

RoleFunctions = new IList<RoleFunction>();
RoleFunctions.Add(
   new RoleFunction 
   { 
      RoleId = Roles.Where( r => r.Value == "Basic User").FirstOrDefault().Key, 
      FunctionId = Functions.Where( f => f.Value == "List Things" ).FirstOrDefault().Key,
      isAuthorized = true
   },
   new RoleFunction 
   { 
      RoleId = Roles.Where( r => r.Value == "Administrator").FirstOrDefault().Key, 
      FunctionId = Functions.Where( f => f.Value == "Add or Edit Things" ).FirstOrDefault().Key,
      isAuthorized = true
   },
   // More binding...
);

到目前为止,我对此感觉良好。所以我去研究AuthorizeCore,看看我需要在那里做什么。然而,根据页面底部的评论,这并没有多大帮助。最后,我或多或少地了解到,该方法需要返回一个bool值。我需要检查其中一个User.Roles数组是否符合通过[AuthorizeFunction("List Things")]传递的权限。

更新(再次):

我有以下代码,看起来它可以满足我的需要(有一种方法需要充实):

/// <summary>An authorization attribute that takes "function name" as a parameter
/// and checks to see if the logged-in user is authorized to use that function.
/// </summary>
public class AuthorizeFunctionAttribute : AuthorizeAttribute 
{
    private IList<KeyValuePair<long, string>> Roles;
    private IList<KeyValuePair<long, string>> Functions;
    private IList<RoleFunction> RoleFunctions;
    public string Function { get; private set; }
    public AuthorizeFunctionAttribute(string FunctionName)
    {
        Function = FunctionName;
        Roles = SetApplicationRoles();
        Functions = SetApplicationFunctions();
        RoleFunctions = SetRoleFunctions();
    }
    protected virtual bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool userIsAuthorized = false;
        foreach (string ur in GetUserRoles(httpContext.Current.Request.Headers["SM_USER"]))
        {
            long roleId = Roles.Where( sr => sr.Value == ur )
                .First().Key;
            long functionId = Functions.Where( sf => sf.Value == Function )
                .First().Key;
            // If any role is authorized for this function, set userIsAuthorized to true.
            // DO NOT set userIsAuthorized to false within this loop.
            if (RoleFunctions.Where(rf => rf.RoleId == roleId && rf.FunctionId == functionId)
                .First().isAuthorized) 
            { 
                userIsAuthorized = true; 
            }
        }
        return userIsAuthorized;
    }

以前,我对创建自定义属性的底层知识了解不够,无法摆脱自己的困境。然而,MSDN的这篇文章告诉了我一开始应该显而易见的事情:自己构建它。所以,一旦我把GetUserRoles()方法组合在一起,我就应该开始了。

ASP.NET安全性:角色名称的单个条目

我认为您可以使用自定义AuthorizeAttribute来解决此问题。在我工作过的一个项目中,他们使用它来访问Active Directory(如本答案所述)。

在你的情况下,它看起来像:

public class AuthorizeWithLDAPAttribute(string functionName) : AuthorizeAttribute 
{
    protected virtual bool AuthorizeCore(HttpContextBase httpContext)
    {
         // check LDAP to verify that user has 
         // a role that's linked to `functionName`
    }
}

接下来,您可以在控制器和/或方法上使用此属性:

[AuthorizeWithLDAP("functionName1")]
public class BlogController : Controller
{
    ....
    [AuthorizeWithLDAP("functionName2")]
    public ViewResult Index()
    {
         return View();
    }
}

控制器现在只能由角色链接到functionName1的用户访问,而方法只能由角色连接到functionName1functionName2的用户访问