(此问题底部已添加更新)

我有一个Web应用程序,它同时使用MVC5和WebAPI2和Autofac for DI。该应用程序使用ASP.NET身份和oAuth承载 token ,尽管后者可能不重要。一切都运行良好,但是此时,我需要在OWIN管道以及其余应用程序中共享相同注入(inject)服务的实例,因此,我试图为MVC和Web设置Autofac的OWIN集成。 API。我似乎很接近-除了AuthorizeAttibutes上的ApiControllers,其他所有内容似乎都可以正常工作。 oAuth过程成功完成,我最终使用了承载 token 登录,但是随后尝试在WebAPI Controller /操作上使用所述 token 进行授权失败。

具体来说,在IsAuthorizedSystem.Web.Http.AuthorizeAttribute方法中,IPrincipal.Identity似乎尚未正确实例化,因为它没有适当的声明,并且IsAuthenticated属性始终为false。即使该代码使用GlobalConfiguration this attribute should work with the OWIN integrations,Autofac的开发人员仍会指示which is not advisable for the OWIN integrations。我看到了多个删除config.SuppressDefaultHostAuthentication()的建议(herehere),尽管不建议这样做,但我尝试了绝望的尝试,但无济于事-对于我的特定配置,这导致IPrincipal返回为null。我还尝试过修改a much simpler example project来在WebAPI Controller 上使用AuthorizeAttribute,但没有成功。在这一点上,我无法尝试,将不胜感激。

这是我的Startup.cs:

[assembly: OwinStartup(typeof (Startup))]
namespace Project.Web
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var builder = new ContainerBuilder();
            builder.RegisterControllers(Assembly.GetExecutingAssembly());
            var config = new HttpConfiguration();
            builder.RegisterHttpRequestMessage(config);
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
            RegisterGeneralTypes(builder);
            var container = builder.Build();
            WebApiConfig.Register(config);
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            WebApiFilterConfig.RegisterGlobalFilters(config.Filters);

            app.UseAutofacMiddleware(container);
            app.UseAutofacWebApi(config);
            app.UseAutofacMvc();
            app.UseWebApi(config);

            ConfigureAuth(app);
        }

        private static void RegisterGeneralTypes(ContainerBuilder builder)
        {
            builder.Register(c => new DomainModelContext())
                .AsSelf()
                .InstancePerRequest();

            builder.Register(c => HttpContext.Current.User.Identity)
                .As(typeof (IIdentity));

            builder.RegisterType<EmailService>()
                .AsImplementedInterfaces()
                .InstancePerRequest();

            builder.Register(c => new IdentityFactoryOptions<DomainUserManager>
            {
                DataProtectionProvider = DataProtectionProvider
            }).InstancePerRequest();

            builder.RegisterType<DomainUserManager>()
                .AsSelf()
                .UsingConstructor(typeof (IIdentityMessageService),
                    typeof (IdentityFactoryOptions<DomainUserManager>),
                    typeof (CustomUserStore))
                .InstancePerRequest();

            builder.RegisterType<CustomUserStore>()
                .AsImplementedInterfaces()
                .AsSelf()
                .InstancePerRequest();

            builder.Register(c => HttpContext.Current.GetOwinContext().Authentication)
                .As<IAuthenticationManager>();
        }
    }
}

和我的Startup.Auth.cs:
public partial class Startup
{
    internal static IDataProtectionProvider DataProtectionProvider;
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
    public static string PublicClientId { get; private set; }

    public void ConfigureAuth(IAppBuilder app)
    {
        var onValidateIdentity = SecurityStampValidator
            .OnValidateIdentity<DomainUserManager, DomainUser, int>(
                validateInterval: TimeSpan.FromMinutes(30),
                regenerateIdentityCallback: (manager, user) =>
                    user.GenerateUserIdentityAsync(manager, CookieAuthenticationDefaults.AuthenticationType),
                getUserIdCallback: id => id.GetUserId<int>());

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            LoginPath = new PathString("/account/login"),

            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = onValidateIdentity
            }
        });
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Configure the application for OAuth based flow
        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            AuthorizeEndpointPath = new PathString("/api/v1/account/externallogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
        };

        // Enable the application to use bearer tokens to authenticate users
        app.UseOAuthBearerTokens(OAuthOptions);

        DataProtectionProvider = app.GetDataProtectionProvider();
    }
}

我认为涵盖了这一点,但是我将很乐意根据要求发布其他代码。

更新

因此,根据jumuro's answer,我根据建议更改了注册顺序。但是,这只是将完全相同的问题从Web API授权转移到了MVC授权。由于在更新之前我已经进行过MVC身份验证,因此我最终尝试按两次在管道中注册身份验证,如下所示:
app.UseAutofacMiddleware(container);
ConfigureAuth(app);
app.UseAutofacWebApi(config);
app.UseAutofacMvc();
app.UseWebApi(config);
ConfigureAuth(app);

这行得通,但是我真的不能说我理解为什么,而且我无法想象重复两次是一件好事。所以现在我有新问题:
  • 合理的做法是,WebAPI需要在
    管道优先,但是为什么MVC在世界上要我注册
    最后验证?
  • 我该如何清理并避免两次调用ConfigureAuth
  • 最佳答案

    您必须以正确的顺序将中间件添加到应用程序管道中。在MVC和Web Api中间件处理请求之前,必须验证承载 token 。

    Configuration()方法中尝试以下顺序:

    public void Configuration(IAppBuilder app)
    {
        ...
        app.UseAutofacMiddleware(container);
        ConfigureAuth(app);
        app.UseAutofacMvc();
        app.UseWebApi(config);
        app.UseAutofacWebApi(config);
        ...
    }
    

    希望对您有所帮助。

    关于asp.net - 通过ASP.NET Identity和Autofac OWIN集成进行授权,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37826551/

    10-12 22:39