2

現在ログインしているユーザーがコントローラーのアクションにアクセスできることを確認できるコンポーネントがあります。

public class ControllerAccessChecker : IControllerAccessChecker
{
    ILifetimeScope _scope;

    public ControllerAccessChecker(ILifetimeScope scope)
    {
        _scope = scope;
    }

    public bool IsAccessible<TController>(Expression<Action<TController>> action, RequestContext requestContext) where TController : Controller
    {
        var actionName = GetActionName(action);
        var result = false;

        using (var childScope = _scope.BeginLifetimeScope())
        {
            var controller = childScope.Resolve<TController>(); 
            result = HasActionPermission(requestContext, actionName, controller);
        }
        return result;
    }

    private static string GetActionName(LambdaExpression actionExpression)
    {
        object operand;
        if (actionExpression.Body as UnaryExpression != null)
        {
            operand = ((UnaryExpression)actionExpression.Body).Operand;
        }
        else
        {
            operand = actionExpression.Body;
        }
        MethodCallExpression methodCallExpression = (MethodCallExpression)operand;
        return methodCallExpression.Method.Name;
    }

    private static bool HasActionPermission(RequestContext requestContext, string actionName, ControllerBase controller)
    {
        var controllerContext = new ControllerContext(requestContext, controller);

        var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());

        var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

        return ActionIsAuthorized(controllerContext, actionDescriptor);
    }


    private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        if (actionDescriptor == null)
            return false;

        AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);

        foreach (Filter authFilter in FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor).Where(x => x.Instance is IAuthorizationFilter))
        {
            ((IAuthorizationFilter)authFilter.Instance).OnAuthorization(authContext);

            if (authContext.Result != null)
                return false;
        }

        return true;
    }
}

ご覧のとおりILifetimeScope、コンストラクターに注入していますが、これが良い方法かどうかはわかりません。また、メソッド内で正しいことを行っているかどうかもわかりませんIsAccessible。この Autofac のスコープ階層アプローチは、私にとって本当に混乱を招きます。

コントローラー用のある種の抽象ファクトリについて考えていましたが、Autofac で実装するのは簡単ではないようです。IIndex<,>ここで、使用と登録に関する記事と回答をいくつか見つけまし.Keyed()たが、このような場合に実際に使用する必要があるとは思いません。つまり、必要なタイプを知っているので、それを求めるだけで簡単になるはずです。

4

1 に答える 1

1

ライフタイムスコープを挿入するのではなく、次を使用できますAutofacDependencyResolver.Current.RequestLifetimeScope-これをWebコンテキストの外部で使用しているのでない限り、私はおそらくそれを使用します。

これの設計に関する1つのことはIsAccessible、実際のコントローラーを解決することです。これは、チェーン全体で、すべての依存関係を解決してインスタンス化することも意味します。メニューシステムまたはすべてのリクエストでこれらの多くを実行している場所でこれを実行している場合、それは多くのコントローラー(およびコントローラーの依存関係)です。また、コントローラーの依存関係が、たとえばデータベース接続やWCFサービスプロキシである場合は、アクセシビリティを確認するだけでもかなりの費用がかかる可能性があります。考慮すべきことがあります。

于 2013-01-25T16:28:40.320 に答える