0

我在 asp.net mvc web api 中的操作上有一个自定义 AuthorizeAttribute。我需要将我的 EF ObjectContext 注入其中。

开发服务器启动后的第一个请求始终有效。以下是失败的。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。这里是:

 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 的其他非 api Web 应用程序中清理我的代码(顺便说一下,FilterAttributeFilterProvider 的工作方式与 IMO 一样)。所以我不介意这个,事实上。

任何人都有更好/更简单的想法,或者对我需要提醒的安全漏洞感到不满,请告诉我。

编辑

从 MVC 4.0 beta 到 RC,很多事情都发生了变化。长话短说,我从这个好人那里获得灵感。MembershipProvider 的创建和 UserRepo 的注入现在进入BeginScope () 方法。干净的?也许。

于 2012-05-31T10:05:10.593 回答