加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-web-api – Autofac,Owin,Webapi并注入AuthorizationSer

发布时间:2020-12-16 07:25:15 所属栏目:asp.Net 来源:网络整理
导读:在阅读有关使用owin和webapi的autofac的问题和文章后,我遇到了注入服务的解决方案,但它不起作用.这是我的代码: public class StartUp{ public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); WebApiConfig.Re
在阅读有关使用owin和webapi的autofac的问题和文章后,我遇到了注入服务的解决方案,但它不起作用.这是我的代码:

public class StartUp
{
    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();
        WebApiConfig.Register(config);

        var builder = new ContainerBuilder();                                    // Create the container builder.
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());         // Register the Web API controllers.

        var authcontext = new AuthContext();

        builder.RegisterInstance(authcontext).AsSelf().SingleInstance();

        //Updated
        //var simpleauth = new SimpleAuthorizationServerProvider();
        //Updated
        // builder.RegisterInstance(simpleauth).SingleInstance().AsSelf().PropertiesAutowired();

        builder.Register(x => new UserStore<IdentityUser>(authcontext)).As<IUserStore<IdentityUser>>();

        //updated

        builder.Register(x =>
        {
            var p = new SimpleAuthorizationServerProvider();
            var userStore = x.Resolve<IUserStore<IdentityUser>>();
            p.userManager = new UserManager<IdentityUser>(userStore);
            return p;
        }).AsSelf().PropertiesAutowired();

        builder.RegisterType<AuthRepository>().As<IAuthRepository>().InstancePerRequest().PropertiesAutowired();

        var container = builder.Build();

        var resolver = new AutofacWebApiDependencyResolver(container);           // Create an assign a dependency resolver for Web API to use.
        config.DependencyResolver = resolver;

        app.UseAutofacMiddleware(container);

        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(config);

        ConfigureOAuth(app,resolver);
    }

    public void ConfigureOAuth(IAppBuilder app,AutofacWebApiDependencyResolver resolver)
    {
        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,TokenEndpointPath = new PathString("/token"),AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),//updated
            Provider =  new SimpleAuthorizationServerProvider()
//resolver.GetService(typeof(SimpleAuthorizationServerProvider)) as SimpleAuthorizationServerProvider
        };

        // Token Generation
        app.USEOAuthAuthorizationServer(OAuthServerOptions);
        app.USEOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }


}

但是在SimpleAuthorizationServerProvider类中,当一个类似ValidateClientAuthentication的方法被调用时,所有的服务都是null,这里是代码:

public readonly IAuthRepository repository;
        public readonly UserManager<IdentityUser> userManager;
        public readonly AuthContext dbContext;

        public SimpleAuthorizationServerProvider()
        {

        }

        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId;
            string clientSecret;

            if (context.TryGetFormCredentials(out clientId,out clientSecret))
            {


                try
                {
                    Client client = await repository.FindClientById(clientId);
                }
            }
        }

你能帮帮我吗?

更新

如果在ConfigureOAuth方法中,我使用以下方法:

OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
            {
                AllowInsecureHttp = true,Provider = resolver.GetService(typeof(SimpleAuthorizationServerProvider)) as SimpleAuthorizationServerProvider
            };

我收到错误:

An exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll but was not handled in user code

Additional information: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime,never from the container itself.

解决方法

当您注册对象的实例而不是类型时,即使您指定的PropertiesAutowired也不会生效,因为Autofac假定您在创建实例时已完成所需的所有工作.如果要连接属性,则需要在OnActivated处理程序中执行此操作.

在这个示例代码中实际上有很多东西在起作用.

> SimpleAuthorizationServerProvider中的值是字段而不是属性,因此PropertiesAutowired不会对它们起作用.
>字段标记为只读,它们从未设置.
>您有UserManager< IdentityUser>注册为lambda但也有PropertiesAutowired不起作用 – 你只能在基于反射的组件上使用PropertiesAutowired(例如,RegisterType< T>).

考虑为您的提供者注册lambda并设置lambda中的所有内容:

builder.Register(c => {
  var p = new SimpleAuthorizationServerProvider();
  p.repository = c.Resolve<UserManager<IdentityUser>>();
  // ...and so on
  return p;
}).AsSelf().SingleInstance();

另外,请记住,如果您注册一个实例(或注册一些东西作为SingleInstance,属性将被解析一次,那就是它.所以,如果你有一些依赖是InstancePerDependency或InstancePerRequest,那就不会按你想象的方式工作 – 他们将被解决一次,之后有效地成为单身人士.

更新1

基于原始和更新的代码,我发现如果您可以查看一些Autofac文档以更好地了解它是如何工作的,那将是一件好事.例如,使用SimpleAuthorizationServerProvider中的字段表明您可能无法完全了解注入如何在Autofac中工作或如何正确注册事物,因此Autofac可以为您完成工作.

> Registration concepts
> Web API integration
> Working with per-request lifetime

例如,查看更新…

>您现在已经为SimpleAuthorizationServerProvider注册了lambda,但是我没有看到您在那里设置存储库字段的位置.
>您在SimpleAuthorizationServerProvider注册时不需要PropertiesAutowired,因为您正在注册lambda,并且属性不会自动装配(如前所述).
>我认为注册InstancePerRequest的唯一组件是AuthRepository,但就像我说的那样,我看不出那个被解析或设置的地方 – 而且这是唯一会产生你注意到的异常的东西. There is an FAQ on dealing with that exact exception that you should look into.

此外,您正在显示正在初始化的两个不同版本的OAuthServerOptions,并且很难分辨哪个版本是“真实的”.

我会建议一个相当重要的重构,以使事情能够正确地使用DI.

更改SimpleAuthorizationServerProvider以停止使用公共字段并将它们添加为构造函数参数,以便Autofac可以为您填充这些内容.

public class SimpleAuthorizationServerProvider
{
  public IAuthRepository Repository { get; private set; }
  public UserManager<IdentityUser> UserManager {get; private set; }
  public AuthContext Context { get; private set; }
  public SimpleAuthorizationServerProvider(
    IAuthRepository repository,UserManager<IdentityUser> userManager,AuthContext context)
  {
    this.Repository = repository;
    this.UserManager = userManager;
    this.AuthContext = context;
  }
}

在启动期间,修复您的注册以删除多余的内容并利用Autofac自动布线优势.

public class StartUp
{
  public void Configuration(IAppBuilder app)
  {
    var config = new HttpConfiguration();
    WebApiConfig.Register(config);

    var builder = new ContainerBuilder();
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Register the auth context instance but skip
    // the extra .AsSelf() and .SingleInstance() because
    // it's implicit.
    builder.RegisterInstance(new AuthContext());

    // Use the lambda to resolve the auth context rather
    // than making a closure over an instance.
    builder.Register(c => new UserStore<IdentityUser>(c.Resolve<AuthContext>()))
           .As<IUserStore<IdentityUser>>();

    // Just register the provider type and let Autofac
    // do the work without all this manual stuff. Skip
    // the .AsSelf() because it's implicit if you don't
    // specify other interfaces and don't auto-wire properties
    // because you don't need it.
    builder.RegisterType<SimpleAuthorizationProvider>();

    // This is fine,but I can't tell where it's used - if
    // you are using it at app startup or OUTSIDE a request,// you will get that exception you noted. Also,unless
    // you're actually using property injection,lose the
    // .PropertiesAutowired() call.
    builder.RegisterType<AuthRepository>()
           .As<IAuthRepository>()
           .InstancePerRequest()
           .PropertiesAutowired();

    var container = builder.Build();
    var resolver = new AutofacWebApiDependencyResolver(container);
    config.DependencyResolver = resolver;

    app.UseAutofacMiddleware(container);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(config);

    ConfigureOAuth(app,resolver);
  }

  public void ConfigureOAuth(IAppBuilder app,AutofacWebApiDependencyResolver resolver)
  {
    var options = new OAuthAuthorizationServerOptions()
    {
      AllowInsecureHttp = true,// If you want the values to be wired up,you have
      // to do a resolve. Note,however,that since you're
      // doing this wire-up at app startup,there's no request
      // scope,so if something in here is registered `InstancePerRequest`
      // you will get an exception.
      Provider =  resolver.GetService(typeof(SimpleAuthorizationServerProvider)) as SimpleAuthorizationServerProvider
    };

    app.USEOAuthAuthorizationServer(options);
    app.USEOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
  }
}

假设所有代码都应该没问题.如果没有设置东西 – 就像SimpleAuthorizationServerProvider属性中的一个属性为null,或者因为它缺少依赖项而得到异常,或者如果你得到关于没有请求范围的异常……那么还有其他东西要去你没有提出你的问题.

再次,请花时间查看文档并熟悉Autofac.我认为你遇到的许多麻烦都是因为对事情的联系有些误解.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读