通过Autofac 4.0配置OAuthAuthorizationServerProvider

时间:2017-11-25 16:23:46

标签: oauth-2.0 asp.net-identity owin autofac

我必须将Oauth与Autofac集成。但出了点问题。我想我理解为什么,但我不知道如何解决它。我让你看看我的代码。

我的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);
    }
}

在这里,我在lifetimescope中解决了我的IMyBusinessObj,而不是在容器中。此对象负责(间接)连接到db,访问​​会话,访问缓存等等...因此它不能是单例。

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

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

  2. 我在启动时配置oauth时实际上没有InstancePerRequest对象...因为在那个上下文中还没有请求。

  3. 所以..我已经明白哪些是我的问题。

    任何想法或提示? 谢谢

1 个答案:

答案 0 :(得分: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模块注册。我无意中正在扫描以&#34; Provider&#34;结尾的课程。并将其注册为RequestPerInstance()。这对我来说是一个问题,因为它正在重新注册我的IOAuthAuthorizationServerProvider作为每个请求实例,在Startup()代码期间无法解析。

我用个人注册代替的问题代码:

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

3. 检查MySessionObj的属性,并查看Autofac正在解析的依赖项(如果有)。确保您明确将依赖项注册为InstancePerRequest()

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

4. 我不确定您的CustomAuthorizationServerProvider对象的自动装配属性,但假设您没有为此类发布完整的代码示例,我会尝试删除{{ 1}}来自它的Autofac注册和对象内部继续使用PropertiesAutowired()来解析这些其他属性。

您能否提供有关您正在观察的错误或错误消息的具体细节?