ASP.NET 安全性:单项角色名称
ASP.NET Security: single entry of role names
我们正在构建一个 ASP.NET 应用程序,并且需要使用企业 LDAP 系统 (Siteminder) 进行身份验证(好处:没有登录对话框)。角色在 LDAP 工具中创建,用户由用户空间管理器分配给角色(阅读:结构必须易于理解)。目前,所有使用该系统的应用程序都使用双重输入流程,即在应用程序中识别的角色被手动输入到 LDAP 系统并分配用户,然后应用程序功能被分配到基于应用程序的控制面板中的角色镜像.这行得通,但令我困扰的是需要双重输入。
我想要实现的是应用程序查询 LDAP 系统以获取分配给应用程序的角色列表(在 LDAP 系统中标识)并填充 role:function 控件与他们一起小组讨论。这部分看起来非常简单。但是,在弄清楚要在 Authorize 属性中放入什么时,我不清楚:
[Authorize(Roles = "Admin, Moderator")]
会变成……什么?
[Authorize(LoadedRoles(r => r.FindAll("some expression that describes the roles that have a particular permission")))]
我真的很喜欢这里的蓝天领域。我读过 this question, and liked - from an architectural standpoint - the answer that suggested making the permissions the roles. But that might not be acceptable to the userland managers that needed to manage users. On the other hand, this question 将事物转换为非字符串资源,但我无法想象如何将其转换为 "roles that have this sort of function included"。
有什么建议吗?
更新:
根据下面@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 看看我需要在那里做什么。但是,根据页面底部的评论,它不是很有帮助。最后我或多或少明白了,该方法需要 return 一个 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;
}
以前我对创建自定义属性的底层知识了解不够,无法按照自己的方式行事。但是,this MSDN article 告诉我一开始对我来说应该很明显的事情:自己构建。所以,一旦我将 GetUserRoles()
方法放在一起,我就应该开始了。
我想你可以使用自定义 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`
}
}
接下来您可以在控制器 and/or 方法上使用此属性:
[AuthorizeWithLDAP("functionName1")]
public class BlogController : Controller
{
....
[AuthorizeWithLDAP("functionName2")]
public ViewResult Index()
{
return View();
}
}
控制器现在只能由角色链接到 functionName1
的用户访问,方法只能由角色链接到 functionName1
和 functionName2
[=17 的用户访问=]
我们正在构建一个 ASP.NET 应用程序,并且需要使用企业 LDAP 系统 (Siteminder) 进行身份验证(好处:没有登录对话框)。角色在 LDAP 工具中创建,用户由用户空间管理器分配给角色(阅读:结构必须易于理解)。目前,所有使用该系统的应用程序都使用双重输入流程,即在应用程序中识别的角色被手动输入到 LDAP 系统并分配用户,然后应用程序功能被分配到基于应用程序的控制面板中的角色镜像.这行得通,但令我困扰的是需要双重输入。
我想要实现的是应用程序查询 LDAP 系统以获取分配给应用程序的角色列表(在 LDAP 系统中标识)并填充 role:function 控件与他们一起小组讨论。这部分看起来非常简单。但是,在弄清楚要在 Authorize 属性中放入什么时,我不清楚:
[Authorize(Roles = "Admin, Moderator")]
会变成……什么?
[Authorize(LoadedRoles(r => r.FindAll("some expression that describes the roles that have a particular permission")))]
我真的很喜欢这里的蓝天领域。我读过 this question, and liked - from an architectural standpoint - the answer that suggested making the permissions the roles. But that might not be acceptable to the userland managers that needed to manage users. On the other hand, this question 将事物转换为非字符串资源,但我无法想象如何将其转换为 "roles that have this sort of function included"。
有什么建议吗?
更新:
根据下面@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 看看我需要在那里做什么。但是,根据页面底部的评论,它不是很有帮助。最后我或多或少明白了,该方法需要 return 一个 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;
}
以前我对创建自定义属性的底层知识了解不够,无法按照自己的方式行事。但是,this MSDN article 告诉我一开始对我来说应该很明显的事情:自己构建。所以,一旦我将 GetUserRoles()
方法放在一起,我就应该开始了。
我想你可以使用自定义 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`
}
}
接下来您可以在控制器 and/or 方法上使用此属性:
[AuthorizeWithLDAP("functionName1")]
public class BlogController : Controller
{
....
[AuthorizeWithLDAP("functionName2")]
public ViewResult Index()
{
return View();
}
}
控制器现在只能由角色链接到 functionName1
的用户访问,方法只能由角色链接到 functionName1
和 functionName2
[=17 的用户访问=]