我需要通过一系列单独的授权规则来保护我的业务对象属性。我希望在各种操作(例如转换为DTO和执行验证规则)(验证当前用户没有权限查看的属性值)期间暂停我的授权规则。

我正在研究的方法将调用包装在使用[ThreadStatic]属性来确定是否应运行授权规则的范围对象中:

public class SuspendedAuthorizationScope : IDisposable
{
    [ThreadStatic]
    public static bool AuthorizationRulesAreSuspended;

    public SuspendedAuthorizationScope()
    {
        AuthorizationRulesAreSuspended = true;
    }

    public void Dispose()
    {
        AuthorizationRulesAreSuspended = false;
    }
}

这是IsAuthorized检查(来自基类):
public bool IsAuthorized(string memberName, AuthorizedAction authorizationAction)
{
    if (SuspendedAuthorizationScope.AuthorizationRulesAreSuspended)
        return true;

    var context = new RulesContext();

    _rules.OfType<IAuthorizationRule>()
        .Where(r => r.PropertyName == memberName)
        .Where(r => r.AuthorizedAction == authorizationAction)
        .ToList().ForEach(r => r.Execute(context));

    return context.HasNoErrors();
}

这是ValidateProperty方法,用于演示用法(来自基类):
private void ValidateProperty(string propertyName, IEnumerable<IValidationRule> rules)
{
    using (new SuspendedAuthorizationScope())
    {
        var context = new RulesContext();
        rules.ToList().ForEach(rule => rule.Execute(context));
         if (HasNoErrors(context))
            RemoveErrorsForProperty(propertyName);
        else
            AddErrorsForProperty(propertyName, context.Results);
    }
    NotifyErrorsChanged(propertyName);
}

我围绕作用域对象进行了一些测试,这些测试表明,只要lambda在using语句的范围内解析,就会使用SuspendedAuthorizationScope.AuthorizationRulesAreSuspended的期望/正确值。

此设计是否有任何明显的缺陷?就线程化而言,我在ASP.NET中是否应该关注什么?

最佳答案

我对您提出的方法有两个担忧:

  • 创建using时未使用SuspendedAuthorizationScope将导致超出预期范围的情况下保留开放访问权限。换句话说,容易犯的错误将导致安全漏洞(尤其是当新员工开始挖掘未知的代码并错过了这种微妙的情况时,尤其要考虑对代码/设计进行过时的验证)。
  • 现在,将此魔术标志附加到ThreadStatic上可以扩大对前一个项目符号的访问范围,因为它可以在处理完当前页面后使用该线程处理另一个请求,并且该授权标志先前未重置,因此可以打开对另一个页面的访问权限。因此,现在授权的范围比应该保留的时间更长,不仅会超出缺少对.Dispose()的调用,而且实际上可能会泄漏到另一个请求/页面以及完全不同的用户。

  • 就是说,我所看到的解决此问题的方法实际上涉及到检查授权并标记一个魔术标志,该标志随后允许绕开,然后将其重置。

    意见建议:
    1.至少要解决最差的变体(上面的第2个问题),您是否可以将Magic Cookie移为您的基页类的成员,并让它的实例字段仅在该页面的范围内有效,而对其他实例无效?
    2.要解决所有情况,是否可以使用Functor或类似的方法传递给授权功能,授权成功后,该功能将启动运行所有逻辑并保证清除的Functor?请参见下面的伪代码示例:
    void myBizLogicFunction()
    {
       DoActionThatRequiresAuthorization1();
       DoActionThatRequiresAuthorization2();
       DoActionThatRequiresAuthorization3();
    }
    
    void AuthorizeAndRun(string memberName, AuthorizedAction authorizationAction, Func privilegedFunction)
    {
        if (IsAuthorized(memberName, authorizationAction))
        {
            try
            {
                AuthorizationRulesAreSuspended = true;
    
                privilegedFunction();
            }
            finally
            {
                AuthorizationRulesAreSuspended = true;
            }
        }
    }
    

    有了以上内容,我认为它可以是静态线程,因为可以保证finally可以运行,因此授权不会泄漏到对privilegedFunction的调用之外。我认为这可行,尽管可以使用其他人的验证和验证...

    关于c# - ThreadStatic和ASP.NET,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22432253/

    10-08 21:01