0

asp.net mvcwebapiのアクションにカスタムAuthorizeAttributeがあります。EFObjectContextを注入する必要があります。

開発サーバーが起動した後の最初のリクエストは常に機能します。失敗するのは次のとおりです。ObjectContextは破棄され、私の一生の間、すべての要求に対していまいましいものを注入する方法を理解できません。

これが私のFilterProviderです。

   public class UnityFilterAttributeFilterProvider : IFilterProvider
    {
        public UnityFilterAttributeFilterProvider(IUnityContainer container)
        {
            _container = container;
        }

        private IUnityContainer _container;


        public IEnumerable<Filter> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
        {
            if (configuration == null)
            {
                throw Error.ArgumentNull("configuration");
            }
            if (actionDescriptor == null)
            {
                throw Error.ArgumentNull("actionDescriptor");
            }

            IEnumerable<Filter> first =
                actionDescriptor.ControllerDescriptor.ControllerType.GetCustomAttributes(true)
                    .Select(instance => new Filter((IFilter)instance, FilterScope.Controller));

            IEnumerable<Filter> second =
                from instance in actionDescriptor.GetFilters()
                select new Filter(instance, FilterScope.Action);

            foreach (var filter in first.Concat(second))
            {
                if (filter.Instance is HeroineAuthorizeAttribute)
                    _container.BuildUp(filter.Instance as HeroineAuthorizeAttribute);
            }


            return first.Concat(second);
        }
    }

_container.BuildUpは最初のリクエストで呼び出されますが、後続のリクエストでは呼び出されません。

それがうまくいかなかったとき、私はApiControllerActionInvokerで2倍になりました。ここにあります:

 public class InjectingActionInvoker : ApiControllerActionInvoker
    {
        private readonly IUnityContainer _container;

        public InjectingActionInvoker(IUnityContainer container)
        {
            _container = container;
        }

        public override System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
            foreach (var filter in actionContext.ActionDescriptor.GetFilters())
            {
                if (filter is HeroineAuthorizeAttribute)
                {
                    var f = filter as HeroineAuthorizeAttribute;
                    f.UserRepository = _container.Resolve<IUserRepository>();
                }

            }
            return base.InvokeActionAsync(actionContext, cancellationToken);
        }
    }

案の定、インジェクションは、後続のリクエストではなく、最初のリクエストで行われます。ただし、これはすべてOnAuthorizationが呼び出された後に行われるため、あまり意味がありません。とにかく言及したいと思いました。

うーん...では、どうすればこれを行うことができますか?

Application_startも表示すると思いました。空白を埋めることができると確信しています。

    var container = CoinUnityContainerFactory.GetUnityContainer();

    DependencyResolver.SetResolver(new HeroineDependencyResolver(container));
    GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new HeroineServiceResolver(container));
4

1 に答える 1

1

最終的に、私は自分のメンバーシッププロバイダーをロールし、SqlMembershipProviderをオーバーライドしました。

ただし、ObjectContextは私のカスタム属性の主な理由ではないため、カスタムメンバーシッププロバイダー自体では問題を解決できません。オブジェクトコンテキストをどこに挿入するかという元の質問がまだ残っていますが、ターゲットのみが変更されています。

MembershipProviderがMembershipUserを中心としているという追加の問題もありますが、私は以前に並列ユーザーを扱ったことがあるので、それは簡単に回避できます。

最後に、これですべてうまくいきました。(以下の編集を参照してください。)

    public override void Init()
    {
        this.AuthorizeRequest += new EventHandler(WebApiApplication_AuthorizeRequest);
        base.Init();
    }

    void WebApiApplication_AuthorizeRequest(object sender, EventArgs e)
    {
        var provider = Membership.Provider as HeroineMembershipProvider;
        if (provider != null)
            provider.UserRepository = _container.Resolve<IUserRepository>();
    }

これはすべてのリクエストと呼ばれ、毎回新しいリポジトリを挿入します。更新された属性は、オブジェクトコンテキストに直接依存するのではなく、Membership.Providerに依存します。

実際にやっていることに気付くまでに少し時間がかかりました。

問題は、FormsAuthenticationを使用していないということです。認証は、ヘッダーで送信される暗号化されたチケットによって行われます。そのため、カスタム認証属性が必要です。MVCは、本質的に私が行っているCookieなしの認証では再生されません。

したがって、私はMembership.Providerを、新しいオブジェクトコンテキストを運ぶための容器としてのみ使用しています。HttpContext.Current.Itemsを使用したほうがよいようです。それが私が思う簡単な答えです。

ただし、最終的には、新しいMembershipProviderを使用すると、FormsAuthenticationが使用されている(そして、ちなみに、FilterAttributeFilterProviderがIMOとして機能する)他の非APIWebアプリでコードをクリーンアップできます。ですから、実際、これは気にしません。

誰もがより良い/より単純な考えを持っているか、私が思い出させる必要があるセキュリティの脆弱性についてのかゆみを持っています、私に知らせてください。

編集

多くのものがMVC4.0ベータからRCに変更されました。話を短くして、私はこの素敵な仲間からインスピレーションを得ています。MembershipProviderの作成とUserRepoの注入は、BeginScope()メソッドで実行されるようになりました。綺麗?多分。

于 2012-05-31T10:05:10.593 に答える