2017-11-25 251 views
2

我必须将Oauth与Autofac集成。但有些事情出错了。我想我明白为什么,但我不知道如何解决它。我让你看看我的代码。通过Autofac 4.0配置OAuthAuthorizationServerProvider

我Autofac配置

{ 
    builder.RegisterType<CustomAuthorizationServerProvider>() 
      .PropertiesAutowired() 
      .SingleInstance(); 

    builder.RegisterType<MyBusinessObj>() 
      .As<IMyBusinessObj>() 
      .InstancePerRequest() 
      .PropertiesAutowired(); 

    //IMySessionObj is a prop inside MyBusinessObj 
    builder.RegisterType<MySessionObj>() 
      .As<IMySessionObj>() 
      .InstancePerRequest() 
      .PropertiesAutowired(); 

    //IMyUnitOfWorkObjis a prop inside MyBusinessObj 
    builder.RegisterType<MyUnitOfWorkObj>() 
      .As<IMyUnitOfWorkObj>() 
      .InstancePerRequest(); 

    ... 
} 

Startup.cs

我有经典配置加上我authorizationServerProvider ..分辨率正如你所看到的,我解决它在容器中。 ..因为它是一个单身人士。

app.UseAutofacMiddleware(_container); 
app.UseAutofacWebApi(config); 

var oauthServerOptions = new OAuthAuthorizationServerOptions 
{ 
    ..., 
    Provider = _container.Resolve<CustomAuthorizationServerProvider>() 
}; 

app.UseOAuthAuthorizationServer(oauthServerOptions); 

app.UseWebApi(config); 

CustomAuthorizationServerProvider.cs

这是怎么了我已经实现了我的CustomAuthorizationServerProvider

public class CustomAuthorizationServerProvider: OAuthAuthorizationServerProvider 
{ 
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
    { 
     var autofacLifetimeScope = OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext); 
     var myBusinessObj = autofacLifetimeScope.Resolve<IMyBusinessObj>(); 
     var xxx = myBusinessObj.DoWork(); 
     ... 
     return Task.FromResult<object>(null); 
    } 

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
    { 
     var myBusinessObj = autofacLifetimeScope.Resolve<IMyBusinessObj>(); 
     var xxx = myBusinessObj.DoWork(); 
     ... 
     context.Validated(ticket); 
    } 
} 

在这里我解决了我的IMyBusinessObj在lifetimescope中,而不是在容器中。这个对象负责(间接)连接到数据库,访问会话,访问缓存等......所以它不能是单身。

我需要它会有一个生命周期的每个请求。 所以这里的问题..我的配置有两个问题。

  1. 我有一个SingleInstance对象内InstancePerRequest对象。我不能这样做。 Troubleshooting Per-Request Dependencies

  2. 当我在启动时配置oauth时,我实际上不能有一个InstancePerRequest对象...因为在该上下文中不存在请求。

所以..我已经理解了哪些是我的问题。

任何想法或提示? 谢谢

回答

1

我有一个非常相似的问题,如果不是相同的。我能够通过执行以下操作来解决它:

1.不要直接从容器中解析IOAuthAuthorizationServerProvider。相反,使用IDependencyResolver。在您的例子:

var oauthServerOptions = new OAuthAuthorizationServerOptions 
{ 
    ..., 
    Provider = (IOAuthAuthorizationServerProvider)resolver.GetService(typeof(IOAuthAuthorizationServerProvider)), 
}; 

这就需要你正确配置HttpConfiguration.DependencyResolver

HttpConfiguration config = new HttpConfiguration(); 

... // Configure unrelated 

var builder = new ContainerBuilder();  

... // set Autofac registrations 

var container = builder.Build(); 

config.DependencyResolver = new AutofacWebApiDependencyResolver(container); 

// THIS is where you configure OAuthAuthorizationServerOptions, using IDependencyResolver to resolve IOAuthorizationServerProvider instead of IContainer 
ConfigureAuth(app, config.DependencyResolver); 

2.我用动力学组件,扫描配置某些Autofac模块注册。我无意中正在扫描以“Provider”结尾的课程,并将它们注册为RequestPerInstance()。这对我来说是一个问题,因为它正在将我的IOAuthAuthorizationServerProvider重新注册为每个请求实例,在Startup()代码中无法解析。

问题代码,我与个别注册替换为:

builder.RegisterAssemblyTypes(executingAssembly) 
    .Where(t => t.Name.EndsWith("Provider")) 
    .AsImplementedInterfaces() 
    .InstancePerRequest();  

MySessionObj检查属性,看看哪些依赖Autofac是解决(如果有的话)。确保您明确注册依赖关系为InstancePerRequest()

通过使用OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);,您将解决对“AutoFacWebRequest”生存期范围的依赖关系,而不是根范围。因此,我的理解是依赖关系解决到这个生命周期范围应该在请求完成后处理,并且不应该导致您的应用程序的未来问题。

4.我不知道属性被自动装配什么你CustomAuthorizationServerProvider对象,但假设你没有张贴此类完整的代码示例,我会尝试去除它PropertiesAutowired()的Autofac登记对象内部继续如果可能,请使用OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);解决这些其他属性。

您能否提供关于您观察到的错误或错误消息的具体细节?