使用 PostSharp AOP 授权方法使用

Authorize method usage using PostSharp AOP

我正在使用基于自定义声明的授权来创建一个面板,该面板的功能取决于用户的访问权限。用户声明存储在缓存 ICashClient 中。 特定菜单仅引用某些控制器方法。

问题是: 只需输入特定方法的直接 link 即可使用由于缺少访问权限而不应使用的方法。

我的想法是创建一个方面,以便可以标记这些特定方法,以防止它们在未经允许的情况下被执行。

我想在OnEntry方法中再次授权。

以下示例允许检查对服务器的请求是否属于 Ajax 类型。

 public override void OnEntry(MethodExecutionArgs args)
        {

            var controller = args.Instance as MyController;

            if (controller != null)
            {

                if (!controller.Request.IsAjaxRequest())
                    throw new Exception ($"{args.Method.Name} invalid AJAX request");
            }

            base.OnEntry(args);
        }

在这种 OnEntry 方法的上下文中,我有什么可能从现金中查询现有数据? 我怎样才能从那里获得这笔现金?

编辑: 我的控制器使用(使用依赖注入)所谓的 QueryProcessor 来检索具有以下方法的请求数据:

 public TResult ExecuteWithCache<TResult>(ICustomQuery<TResult> query)
        {
            try
            {
                //class for creating fingerprint of query 
                var customQueryHash = (ICustomQueryHash<TResult>)query;

                //fingerprint of the query 
                var queryString = customQueryHash.GetQueryHash();    

                //cash which might holds data
                var cachedResult = _cacheClient.Get<TResult>(queryString);




                 ...
             }
             catch(){}


  }

_cashClient 是扩展 ICashClient 的实现。

我知道您需要在您的自定义方面 class 中访问依赖项,并且此依赖项通常使用依赖项注入来解决。在这种特殊情况下,您想要访问 QueryProcessor.

的实例

依赖注入框架无法自动解决方面的依赖关系,因为该框架无法控制方面的构造和生命周期。然而,有许多方法可用于在方面内使用依赖项。它们在本文档部分中进行了描述:http://doc.postsharp.net/consuming-dependencies

下面是一些从方面消费依赖的方法的简短描述。您可以根据您的项目和您使用的依赖框架选择最佳方法。

Global service locator. DI 框架通常提供一种方法来查询特定实例的当前对象图(例如 context.GetInstance<T>())。

public override void OnEntry(MethodExecutionArgs args)
{
    var queryProcessor = ServiceLocator.GetInstance<IQueryProcessor>();
}

Global composition container. Some DI frameworks also allow you to satisfy new object's dependencies after the initial graph has been constructed. You can override RuntimeInitialize 方法在初始化方面实例时导入依赖项。

[PSerializable]
public class MyAspect : OnMethodBoundaryAspect
{
    [Import]
    public IQueryProcessor QueryProcessor { get; set; }

    public override void RuntimeInitialize(MethodBase method)
    {
        ServiceInjector.BuildObject(this);
    }
}

Import dependencies from the target object. When the dependencies are stored in properties or fields of the target object, you can import them using [ImportMember] advice. Your aspect has to implement IInstanceScopedAspect 在这种情况下。

[PSerializable]
public class MyAspect : OnMethodBoundaryAspect, IInstanceScopedAspect
{
    [ImportMember("QueryProcessor", IsRequired = true)] 
    public Property<IQueryProcessor> QueryProcessor;

    public override void OnEntry(MethodExecutionArgs args)
    {
        this.QueryProcessor.Get().ExecuteWithCache(/* ... */);
    }

    object IInstanceScopedAspect.CreateInstance(AdviceArgs adviceArgs)
    {
        return this.MemberwiseClone();
    }

    void IInstanceScopedAspect.RuntimeInitializeInstance()
    {
    }
}