- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 MVC 项目,我们在其中使用派生自 System.Web.Mvc.AuthorizeAttribute
的自定义属性实现了安全性。这放置在我们希望通过派生自 System.Web.Mvc.Controller
的 MVC Controller 上的自定义授权来保护的方法上。我们还使用 Autofac for DI (IoC) 将自动化服务注入(inject)到我们的自定义安全过滤器中。我们现在还在我们的项目中添加 Web API Controller ,它派生自 System.Web.Http.ApiController
。我遇到的问题是,当您想在使用 Web API 时将 DI 包含在过滤器中时,您似乎必须使用 Autofac DI 使用其流畅的 api 注册每个过滤器实例或整个 Controller 。查看autofac documentation了解更多详情。
对于 MVC Controller ,我们只需添加属性,无需额外注册。现在对于 ApiControllers,我们需要使用流畅的方法注册该属性(过滤器)实例,不需要将此属性应用于方法/类本身。我宁愿保持一切一致,更不用说更容易维护,通过仅将这些过滤器作为属性应用而不是使用流畅的方法。恕我直言,这是一种更简洁的方法,尤其是在可能有超过 100 个安全实现的更大的解决方案中。
我一直在尝试创建一个方法来在 Web API Controller 上注册应用过滤器的所有实例,但似乎 Autofac 实现不适合这个。任何人都可以建议如何绕过此限制或在运行时注册一次过滤器而不必为每个过滤器实例编写重复代码的替代方法吗?
ModuleAccessAuthorizationAttribute
- 这是实现 Autofac.Integration.WebApi.IAutofacAuthorizationFilter
MyController
- 这是一个实现 System.Web.Http.ApiController
这行得通
builder.Register(c => new ModuleAccessAuthorizationAttribute(c.Resolve<IAuthenticationFactory>())) // the constructor actually takes much more information which varies each time it is applied but that is out of the scope of this question
.AsWebApiAuthorizationFilterFor<MyController>(c => c.Get()) // Get() is one of the methods that has needs to have the filter applied to it
.InstancePerRequest();
我想改成这样
public class MyController : ApiController {
[ModuleAccessAuthorizationAttribute]
public IHttpActionResult Get()
}
public static void RegisterWebApiSecurityFilter(ContainerBuilder builder)
{
var securedMembers = typeof(DependencyInjectionConfig).Assembly.ExportedTypes
.Where(x => !x.IsAbstract // not abstract
&& x.Name.EndsWith("Controller", StringComparison.Ordinal) // name ends in controller
&& !x.GetCustomAttributes<ObsoleteAttribute>().Any(y => y.IsError) // not marked as obsolete
&& (x.IsSubclassOf(typeof(System.Web.Http.ApiController)))) // implements ApiController
.SelectMany(x => x.GetMembers(BindingFlags.Public | BindingFlags.Instance)) // public instance members
.Where(x => x.GetCustomAttributes<ModuleAccessAuthorizationAttribute>().Any()) // marked with my custom attribute
.Select(x => x)
.ToList();
foreach (var securedMember in securedMembers) // iterate over collection
{
var attribute = securedMember.GetCustomAttribute<ModuleAccessAuthorizationAttribute>(); // get the attribute instance
var declaringClass = securedMember.DeclaringType; // get the declaring (class) type
builder.Register(c => ModuleAccessAuthorizationAttribute(c.Resolve<IAuthenticationFactory>()))
.AsWebApiAuthorizationFilterFor() // this is where I need help, it seems this is generic only and I cannot explicitly pass in my reflected type declaringClass
.InstancePerRequest();
}
}
最佳答案
不幸的是,AsWebApiAuthorizationFilterFor
的重载没有 controllerType 参数。如果您查看 AsWebApiAuthorizationFilterFor
的源代码方法你可以看到实现如下:
public static IRegistrationBuilder<object, IConcreteActivatorData, SingleRegistrationStyle>
AsWebApiAuthorizationFilterFor<TController>(this IRegistrationBuilder<object, IConcreteActivatorData, SingleRegistrationStyle> registration)
where TController : IHttpController
{
return AsFilterFor<IAutofacAuthorizationFilter, TController>(registration, AutofacWebApiFilterProvider.AuthorizationFilterMetadataKey);
}
AsFilterFor
是:
static IRegistrationBuilder<object, IConcreteActivatorData, SingleRegistrationStyle>
AsFilterFor<TFilter, TController>(IRegistrationBuilder<object, IConcreteActivatorData, SingleRegistrationStyle> registration, string metadataKey)
where TController : IHttpController
{
if (registration == null) throw new ArgumentNullException("registration");
var limitType = registration.ActivatorData.Activator.LimitType;
if (!limitType.IsAssignableTo<TFilter>())
{
var message = string.Format(CultureInfo.CurrentCulture, RegistrationExtensionsResources.MustBeAssignableToFilterType,
limitType.FullName, typeof(TFilter).FullName);
throw new ArgumentException(message, "registration");
}
var metadata = new FilterMetadata
{
ControllerType = typeof(TController),
FilterScope = FilterScope.Controller,
MethodInfo = null
};
return registration.As<TFilter>().WithMetadata(metadataKey, metadata);
}
有了这些信息,您可以轻松地 fork RegistrationExtensions
类并添加满足您需要的新重载。
即:
public static class MyRegistrationExtensions
{
public static IRegistrationBuilder<object, IConcreteActivatorData, SingleRegistrationStyle>
AsWebApiAuthorizationFilterFor(this IRegistrationBuilder<object, IConcreteActivatorData, SingleRegistrationStyle> registration, Type controllerType)
{
return AsFilterFor<IAutofacAuthorizationFilter>(registration, AutofacWebApiFilterProvider.AuthorizationFilterMetadataKey, controllerType);
}
static IRegistrationBuilder<object, IConcreteActivatorData, SingleRegistrationStyle>
AsFilterFor<TFilter>(IRegistrationBuilder<object, IConcreteActivatorData, SingleRegistrationStyle> registration, string metadataKey, Type controllerType)
{
if (registration == null) throw new ArgumentNullException("registration");
if (controllerType == null) throw new ArgumentNullException("controllerType");
if (!controllerType.IsAssignableTo<IHttpController>()) throw new ArgumentNullException("controllerType");
var limitType = registration.ActivatorData.Activator.LimitType;
if (!limitType.IsAssignableTo<TFilter>())
{
var message = string.Format(CultureInfo.CurrentCulture, RegistrationExtensionsResources.MustBeAssignableToFilterType,
limitType.FullName, typeof(TFilter).FullName);
throw new ArgumentException(message, "registration");
}
var metadata = new FilterMetadata
{
ControllerType = controllerType,
FilterScope = FilterScope.Controller,
MethodInfo = null
};
return registration.As<TFilter>().WithMetadata(metadataKey, metadata);
}
}
关于c# - Autofac Web Api 过滤器 - 在运行时声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34511916/
我有一个泛型类( GenericClass ),它依赖于泛型类型( IGenericDependency )。这种依赖也是通用的。 public class GenericClass {
虽然我通常认为 Autofac 文档(在 wiki 上)很有帮助,但关于 XML 配置和模块的部分对我来说有点不清楚。现在,我有一个示例工作(我在下面介绍),但我不确定它是否代表了 Autofac 上
我是 autofac 的新手(使用 2.1.14.854),我仍在努力理解 我有一个接口(interface),这个接口(interface)有一个或多个实现,并且应该按特定顺序触发这些实现。 例如:
使用Autofac,可以做到这一点吗?我没有实例的类型。 var instance = container.Resolve("someStringKey"); 从一些谷歌搜索来看,这似乎不可能,但我想
我有一个进行数据处理的应用程序。有 class Pipeline { IEnumerable Filters {get; set;} 我将过滤器实现注册为 builder.RegisterType
我正在尝试将域事件引入项目中。 Udi Dahan 的帖子 - http://www.udidahan.com/2009/06/14/domain-events-salvation/ 中描述了这一概念
假设这个场景: public class B {}; public class C { public C(B b){} } 要从 Autofac 容器解析 C,我必须将 B 和 C 注册到容
我正在为第 3 方应用程序构建一个插件,我的插件使用 Autofac 来连接各种组件。容器是在应用程序启动时构建的,但主机应用程序稍后会调用我的命令。 调用命令时,主机应用程序会提供一些它定义的类型实
我有一个银行/集合,它在内存中缓存对象的实例,以便每个请求不需要返回到数据存储。我希望 Autofac 提供该银行的一个实例,但在 x 秒后使其过期,以便在下一个请求时创建一个新实例。我很难理解如何设
有人可以用简单的英语解释一下我放置问号的代码行的作用吗?或者给我指点一篇阐明这一点的文章。此代码用于在 autofac 容器中注册依赖项 var builder = new Autofac.Conta
我有以下类(class): public class Errors { private readonly string _connectionString; public Errors
假设所有依赖项都已在程序开始时注册。在程序的后面部分,如何使用 AutoFac 使用无参数构造函数创建一个新对象并将注册的属性注入(inject)到该对象中? 最佳答案 您可以使用 Propertie
我使用以下代码进行注册: builder.RegisterType().Named(".VCF"); builder.RegisterType().Named(".VCARD
我有一个工厂接口(interface)(连同具体实现): // foo.dll interface IFooProvider { T GetFoo() where T : Ba
我遇到的情况是,发布者和消费者位于同一个应用程序中。我正在使用 autofac。 据我了解,我需要 2 个具有 2 个端点的总线实例,一个用于发布者,一个用于订阅者。 我正在使用 autofac,但我
我正在使用 Autofac 构造函数注入(inject)。我需要弄清楚如何将单个对象实例注入(inject)多个构造函数参数,而不需要在容器设置阶段显式解析每个参数。 我有一个复杂的场景,可以通过这种
我们在我们的 PCL (Profile259) 中使用 Autofac 3.5.2,Nuget 告诉我们版本 4.1 可用,但当我们尝试更新它时,Nuget 失败并显示以下消息: “您正在尝试将此软件
我的情况是发布者和消费者坐在同一个应用程序中。我正在使用 autofac。 据我了解,我需要 2 个具有 2 个端点的总线实例,一个用于发布者,一个用于订阅者。 我正在使用 autofac,但我不知道
在 Autofac 2.1 的 beta 版本中,支持自动解析 Lazy如 Nicholas Blumhardt 的 Lazing Around with Autofac 中所述博客文章。 The c
我有这个类要在单元测试中实例化: public class Customer { internal Customer(Guid id) { // initialize prop
我是一名优秀的程序员,十分优秀!