2017-11-25 249 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);解決這些其他屬性。

您能否提供關於您觀察到的錯誤或錯誤消息的具體細節?