[英]ASP.Net Identity Check for multiple roles to get access
是否有可能在授予訪問權限之前獲得asp.net身份要求2個角色的成員身份?
我的系統中有2層權限。 首先是允許訪問某些功能的公司類型,其次是限制特定方法和使用權的公司類型。
CompanyType= Host,Expert,Manufacturer,Supplier,Consultant
Accesslevel= Admin,ReadOnly,ReadWrite
我希望能夠做這樣的事情:
[Authorize(Roles = "Expert && ReadWrite || ReadOnly")]
目標是擁有一種同時處理這兩種角色的方式:
HostAdmin, HostReadOnly, HostReadWrite, ExpertAdmin ....
謝謝你的時間。
是的,您可以要求多個角色,只需添加更多授權屬性即可:
[Authorize(Roles="members")]
[Authorize(Roles="admin")]
這將要求用戶同時具有成員和管理員角色
有關更多詳細信息-> 允許多個角色訪問控制器操作
我創建了一個自定義過濾器屬性來滿足您的需求。 我做了一些簡化:我將&&
更改為&
和||
到|
。 解析器還支持xor ^
,不支持!
和括號
[CustomAuthorize(Roles = "Expert & (ReadWrite | ReadOnly)")]
這是自定義授權屬性
/// <summary>
/// [CustomAuthorize(Roles = "A & (!B | C) ^ D")]
/// </summary>
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
/*
* Exp -> SubExp '&' SubExp // AND
* Exp -> SubExp '|' SubExp // OR
* Exp -> SubExp '^' SubExp // XOR
* SubExp -> '(' Exp ')'
* SubExp -> '!' Exp // NOT
* SubExp -> RoleName
* RoleName -> [a-z]
*/
private const char TokenSeparator = ' ';
private const char TokenAnd = '&';
private const char TokenOr = '|';
private const char TokenXor = '^';
private const char TokenNot = '!';
private const char TokenParentheseOpen = '(';
private const char TokenParentheseClose = ')';
abstract class Node
{
public abstract bool Eval(IPrincipal principal);
}
abstract class UnaryNode : Node
{
private readonly Node _expression;
public Node Expression
{
get { return _expression; }
}
protected UnaryNode(Node expression)
{
_expression = expression;
}
}
abstract class BinaryNode : Node
{
private readonly Node _leftExpression;
private readonly Node _rightExpression;
public Node LeftExpression
{
get { return _leftExpression; }
}
public Node RightExpression
{
get { return _rightExpression; }
}
protected BinaryNode(Node leftExpression, Node rightExpression)
{
_leftExpression = leftExpression;
_rightExpression = rightExpression;
}
}
class AndNode : BinaryNode
{
public AndNode(Node leftExpression, Node rightExpression)
: base(leftExpression, rightExpression)
{
}
public override bool Eval(IPrincipal principal)
{
return LeftExpression.Eval(principal) && RightExpression.Eval(principal);
}
}
class OrNode : BinaryNode
{
public OrNode(Node leftExpression, Node rightExpression)
: base(leftExpression, rightExpression)
{
}
public override bool Eval(IPrincipal principal)
{
return LeftExpression.Eval(principal) || RightExpression.Eval(principal);
}
}
class XorNode : BinaryNode
{
public XorNode(Node leftExpression, Node rightExpression)
: base(leftExpression, rightExpression)
{
}
public override bool Eval(IPrincipal principal)
{
return LeftExpression.Eval(principal) ^ RightExpression.Eval(principal);
}
}
class NotNode : UnaryNode
{
public NotNode(Node expression)
: base(expression)
{
}
public override bool Eval(IPrincipal principal)
{
return !Expression.Eval(principal);
}
}
class RoleNode : Node
{
private readonly string _roleName;
public string RoleName
{
get { return _roleName; }
}
public RoleNode(string roleName)
{
_roleName = roleName;
}
public override bool Eval(IPrincipal principal)
{
return principal.IsInRole(RoleName);
}
}
private Node _expression;
void Parse(string text)
{
if (text == null) throw new ArgumentNullException("text");
var delimiters = new[] { TokenSeparator, TokenAnd, TokenOr, TokenXor, TokenNot, TokenParentheseOpen, TokenParentheseClose };
List<string> tokens = new List<string>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
if (c == TokenSeparator)
continue;
if (delimiters.Contains(c))
{
if (sb.Length > 0)
{
tokens.Add(sb.ToString());
sb.Clear();
}
tokens.Add(c.ToString(CultureInfo.InvariantCulture));
}
else
{
sb.Append(c);
}
}
if (sb.Length > 0)
{
tokens.Add(sb.ToString());
}
_expression = Parse(tokens.ToArray());
}
Node Parse(string[] tokens)
{
int index = 0;
return ParseExp(tokens, ref index);
}
Node ParseExp(string[] tokens, ref int index)
{
Node leftExp = ParseSubExp(tokens, ref index);
if (index > tokens.Length)
return leftExp;
string token = tokens[index];
if (token == "&")
{
index++;
Node rightExp = ParseSubExp(tokens, ref index);
return new AndNode(leftExp, rightExp);
}
else if (token == "|")
{
index++;
Node rightExp = ParseSubExp(tokens, ref index);
return new OrNode(leftExp, rightExp);
}
else if (token == "^")
{
index++;
Node rightExp = ParseSubExp(tokens, ref index);
return new XorNode(leftExp, rightExp);
}
else
{
throw new Exception("Expected '&' or '|' or EOF");
}
}
Node ParseSubExp(string[] tokens, ref int index)
{
string token = tokens[index];
if (token == "(")
{
index++;
Node node = ParseExp(tokens, ref index);
if (tokens[index] != ")")
throw new Exception("Expected ')'");
index++; // Skip ')'
return node;
}
else if (token == "!")
{
index++;
Node node = ParseExp(tokens, ref index);
return new NotNode(node);
}
else
{
index++;
return new RoleNode(token);
}
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null) throw new ArgumentNullException("httpContext");
IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated)
{
return false;
}
if (_expression == null)
{
Parse(Roles);
}
if (_expression != null)
{
return _expression.Eval(user);
}
return true;
}
}
否則,您可以使用默認的AuthorizeAttribute
// (role1 OR role2) AND (role3 OR role4)
[Authorize(Roles = "Role1, Role2")]
[Authorize(Roles = "Role3, Role4")]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.