无法在Autofac中使用此文件。

huangapple go评论68阅读模式
英文:

I can't use this file in autofac

问题

你想要使用Keycloak执行JWT身份验证,但在项目中使用Autofac添加Keycloak服务时出现以下错误。

Autofac.Core.DependencyResolutionException: 在激活Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator -> Microsoft.AspNetCore.Authorization.DefaultAuthorizationService -> Microsoft.AspNetCore.Authorization.DefaultAuthorizationHandlerProvider -> λ: Microsoft.AspNetCore.Authorization.IAuthorizationHandler[] -> InventoryManagement.API.Authorization.Decision.DecisionRequirementHandler 期间引发了异常。
---> Autofac.Core.DependencyResolutionException: 在类型'InventoryManagement.API.Authorization.Decision.DecisionRequirementHandler'上,使用'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'找到的构造函数中,无法使用可用的服务和参数调用任何构造函数:
无法解析构造函数的参数'Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor',构造函数为'Void .ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.Extensions.Options.IOptionsMonitor`1[Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions])'。

这个错误表明在DecisionRequirementHandler 类的构造函数中,Autofac 无法解析 Microsoft.AspNetCore.Http.IHttpContextAccessor 参数。

你可以尝试以下步骤来解决这个问题:

  1. 确保你已正确注册 IHttpContextAccessor 服务。通常,你需要在 Startup.cs 文件中的 ConfigureServices 方法中添加以下代码:
services.AddHttpContextAccessor();

这会确保 IHttpContextAccessor 可以被解析并注入到 DecisionRequirementHandler 类中。

  1. 确保你的 Autofac 配置正确。确保 AutofacServiceProviderFactory 正确配置,并且容器已经正确加载了你的 RepositoryServiceModule。

  2. 确保你的依赖项包已经正确安装,特别是 Microsoft.AspNetCore.Authorization 和 Microsoft.AspNetCore.Authentication.JwtBearer。

如果你仍然遇到问题,可能需要检查其他配置或依赖项,以确保它们与你的代码一起正常工作。希望这些建议对解决你的问题有所帮助。

英文:

I want to perform jwt auth authentication with Keycloak. I am using Autofac in my project and when I add the keycloak service, I get an error as follows.

  Autofac.Core.DependencyResolutionException: An exception was thrown while activating Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator -> Microsoft.AspNetCore.Authorization.DefaultAuthorizationService -> Microsoft.AspNetCore.Authorization.DefaultAuthorizationHandlerProvider -> λ:Microsoft.AspNetCore.Authorization.IAuthorizationHandler[] -> InventoryManagement.API.Authorization.Decision.DecisionRequirementHandler.
  ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'InventoryManagement.API.Authorization.Decision.DecisionRequirementHandler' can be invoked with the available services and parameters:
  Cannot resolve parameter 'Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor' of constructor 'Void .ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.Extensions.Options.IOptionsMonitor`1[Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions])'.
     at Autofac.Core.Activators.Reflection.ReflectionActivator.<>c__DisplayClass12_0.<UseSingleConstructorActivation>b__0(ResolveRequestContext ctxt, Action`1 next)
     at Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
     at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
     --- End of inner exception stack trace ---
     at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
     at Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
     at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action`1 next)
     at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
     at Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(ResolveRequest request)
     at Autofac.Core.Resolving.ResolveOperation.Execute(ResolveRequest request)
     at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(ResolveRequest request)
     at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
     at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
     at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
     at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType)
     at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetRequiredService(Type serviceType)
     at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
     at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
     at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
     at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
     at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
     at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

  HEADERS
  =======
  Accept: */*
  Host: localhost:2003
  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36
  Accept-Encoding: gzip, deflate, br
  Accept-Language: tr,en;q=0.9,tr-TR;q=0.8,en-US;q=0.7
  Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3QUE0dU1DUVFYdWdxQ0RLRXVIZUxEUE0xNFRja2swYjBEWkh2d0Z4T3Y4In0.eyJleHAiOjE2NzcyMTc1NDUsImlhdCI6MTY3NzIxNTc0NSwianRpIjoiOGUyMzQ4NTUtOGQ5MS00NzllLWFjMTEtZDc2ZGI1ZjI2OTRjIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoyMDExL3JlYWxtcy9FbmVyeWFJbnZlbnRvcnlBcGlSZWFsbSIsImF1ZCI6ImFwaS1pbnZlbnRvcnkiLCJzdWIiOiJkNzcyMzNmNC01ZTE5LTQ1YmEtYmYwYi0xMWJlNmY0NmNlM2EiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhcGktaW52ZW50b3J5Iiwic2Vzc2lvbl9zdGF0ZSI6ImQ4NTY0MzliLTg1YTAtNDZlNi04NjY2LWFjMjdmNmI3MTA0NSIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiIsImRlZmF1bHQtcm9sZXMtZW5lcnlhaW52ZW50b3J5YXBpcmVhbG0iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhcGktaW52ZW50b3J5Ijp7InJvbGVzIjpbIlN1cGVyIEFkbWluIFJvbGUiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sImF1dGhvcml6YXRpb24iOnsicGVybWlzc2lvbnMiOlt7InJzaWQiOiJkMWFmNjc4NC04OTE1LTRhMGMtYTY4MS1jZTY4M2M5NDg4ODEiLCJyc25hbWUiOiJEZWZhdWx0IFJlc291cmNlIn0seyJzY29wZXMiOlsiZ2V0IiwidXBkYXRlIiwiY3JlYXRlIiwiZGVsZXRlIl0sInJzaWQiOiI0Njk5OTM3Zi0xYTMzLTRiOTItYTI3NS00YzhhMGRjNWM3MjMiLCJyc25hbWUiOiJjb21wYW55In1dfSwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCIsInNpZCI6ImQ4NTY0MzliLTg1YTAtNDZlNi04NjY2LWFjMjdmNmI3MTA0NSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6ImZhdGloIG1hbHllbWV6IiwicHJlZmVycmVkX3VzZXJuYW1lIjoibWFsZngwMDEiLCJnaXZlbl9uYW1lIjoiZmF0aWgiLCJmYW1pbHlfbmFtZSI6Im1hbHllbWV6IiwiZW1haWwiOiJmYXRpaC5tYWx5ZW1lekBlbmVyeWEuY29tLnRyIn0.c-F6NOMOCTire15K7mtjAe0nyGfraL1GohyQ_g_e0yhD6O16SUB38ylF6_NepaMdd9YHwS0y52mf5g8w6f-2KHao-_pzsX7F63IBmXSQVIgEk2RV_UCE-5x3JRw3R-YLLIXXeWC5cWNHWHopUacuOU6HwqUglzfzifxFx_lsWVuaF5m2tc7UYDCSH86swRLuyl7WUESPTD2By7znKkhRg1q3e7yQOEi5d8VEgU9RX5id1BNV9bY_PxqY0sWUmiw-tjeyNTeVMHgvji4DSNzHmcGIWJKY5ySSgOwKE2MUt6BdhGo-g_Neje0YDR75tWu_ayXUm9ALgiFCeJr6ZwuYeQ
  Cookie: _pk_id.1.1fff=da2f7a0a3436376b.1676617944.
  Referer: https://localhost:2003/swagger/index.html
  sec-ch-ua: "Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"
  sec-ch-ua-mobile: ?0
  sec-ch-ua-platform: "Windows"
  sec-fetch-site: same-origin
  sec-fetch-mode: cors
  sec-fetch-dest: empty

In my main project, I made a definition as follows.
Program.cs

  builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
  builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => containerBuilder.RegisterModule(new RepositoryServiceModule()));



  #region JWT
  var jwtOptions = builder.Configuration.GetSection("JwtBearer").Get<JwtBearerOptions>();
  builder.Services
     .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
     .AddJwtBearer(options =>
     {
        options.Authority = jwtOptions.Authority;
        options.Audience = jwtOptions.Audience;
        options.RequireHttpsMetadata = false;
        options.TokenValidationParameters = new TokenValidationParameters
        {
              NameClaimType = "preferred_username",
              RoleClaimType = "role" 
        };
     });

  builder.Services.AddTransient<IClaimsTransformation>(_ => new KeycloakRolesClaimsTransformation("role", jwtOptions.Audience));

  builder.Services.AddAuthorization(options =>
  {
     #region Decision Requirements
     options.AddPolicy("company#get", builder => builder.AddRequirements(new DecisionRequirement("company", "get")));
     options.AddPolicy("company#create", builder => builder.AddRequirements(new DecisionRequirement("company", "create")));
     options.AddPolicy("company#update", builder => builder.AddRequirements(new DecisionRequirement("company", "update")));
     options.AddPolicy("company#delete", builder => builder.AddRequirements(new DecisionRequirement("company", "delete")));
     #endregion
  });

  builder.Services.AddHttpClient<KeycloakServiceTest>(client =>
  {
     client.BaseAddress = new Uri(builder.Configuration["KeycloakResourceUrl"]);
  });
  builder.Services.AddHttpClient<IdentityModel.Client.TokenClient>();
  builder.Services.AddSingleton(builder.Configuration.GetSection("ClientCredentialsTokenRequest").Get<ClientCredentialsTokenRequest>());
  #endregion

This is how I define the autofac file

  namespace InventoryManagement.API.Modules
  {
     public class RepositoryServiceModule : Module
     {
        protected override void Load(ContainerBuilder builder)
        {
              builder.RegisterGeneric(typeof(Service<>)).As(typeof(IService<>)).InstancePerLifetimeScope();

              builder.RegisterGeneric(typeof(ServiceWithDto<,>)).As(typeof(IServiceWithDto<,>)).InstancePerLifetimeScope();

              builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();

              #region TEST
              builder.RegisterType<DecisionRequirementHandler>().As<IAuthorizationHandler>().SingleInstance();
              #endregion

              var apiAssembly = Assembly.GetExecutingAssembly();
              var repoAsssembly = Assembly.GetAssembly(typeof(DataContext));
              var serviceAssembly = Assembly.GetAssembly(typeof(AutoMapperProfile));


              builder.RegisterAssemblyTypes(apiAssembly, repoAsssembly, serviceAssembly)
                 .Where(x => x.Name.EndsWith("Repository"))
                 .AsImplementedInterfaces()
                 .InstancePerLifetimeScope();

              builder.RegisterAssemblyTypes(apiAssembly, repoAsssembly, serviceAssembly)
                 .Where(x => x.Name.EndsWith("Service"))
                 .AsImplementedInterfaces()
                 .InstancePerLifetimeScope();
        }
     }
  }

This is how I defined the DecisionHandler file,
DecisionRequirementHandler.cs

  namespace InventoryManagement.API.Authorization.Decision
  {
     public class DecisionRequirementHandler : AuthorizationHandler<DecisionRequirement>
     {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IOptionsMonitor<JwtBearerOptions> _options;

        public DecisionRequirementHandler(IHttpContextAccessor httpContextAccessor, IOptionsMonitor<JwtBearerOptions> options)
        {
              _httpContextAccessor = httpContextAccessor;
              _options = options;
        }

        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, DecisionRequirement requirement)
        {
              var options = _options.Get(JwtBearerDefaults.AuthenticationScheme);
              var httpContext = _httpContextAccessor.HttpContext;
              if (httpContext != null && httpContext.User.Identity != null && !httpContext.User.Identity.IsAuthenticated)
              {
                 context.Fail();
                 return;
              }

              var data = new Dictionary<string, string>();
              data.Add("grant_type", "urn:ietf:params:oauth:grant-type:uma-ticket");
              data.Add("response_mode", "decision");
              data.Add("audience", options.Audience);
              data.Add("permission", $"{requirement.Resource}#{requirement.Scope}");

              var client = new HttpClient();
              var token = await httpContext.GetTokenAsync(JwtBearerDefaults.AuthenticationScheme, "access_token");
              client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

              var configuration = await options.ConfigurationManager.GetConfigurationAsync(CancellationToken.None);
              var response = await client.PostAsync(configuration.TokenEndpoint, new FormUrlEncodedContent(data));

              if (response.IsSuccessStatusCode)
              {
                 context.Succeed(requirement);
                 return;
              }

              context.Fail();
        }
     }
  }

DecisionRequirement.cs

  namespace InventoryManagement.API.Authorization.Decision
  {
     public class DecisionRequirement : IAuthorizationRequirement
     {
        public string Resource { get; }
        public string Scope { get; }

        public DecisionRequirement(string resource, string scope)
        {
              Resource = resource;
              Scope = scope;
        }
     }
  }

But I'm getting an error, is there a way to fix it?

答案1

得分: 1

根据下面的错误消息:

Autofac.Core.DependencyResolutionException: 激活 Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator 时引发异常 -> Microsoft.AspNetCore.Authorization.DefaultAuthorizationService -> Microsoft.AspNetCore.Authorization.DefaultAuthorizationHandlerProvider -> λ:Microsoft.AspNetCore.Authorization.IAuthorizationHandler[] -> InventoryManagement.API.Authorization.Decision.DecisionRequirementHandler。
---> Autofac.Core.DependencyResolutionException: 在类型 InventoryManagement.API.Authorization.Decision.DecisionRequirementHandler 上,使用 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' 找不到任何构造函数可通过可用的服务和参数调用:
无法解析构造函数 'Void .ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.Extensions.Options.IOptionsMonitor`1[Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions])' 的参数 'Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor'。

我们应该注册 HttpContextAccessorJwtBearerOptions 来解决这个问题。

builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
builder.Register(c => c.Resolve<IOptions<JwtBearerOptions>>().Value).As<JwtBearerOptions>();
英文:

According the error message below:

 Autofac.Core.DependencyResolutionException: An exception was thrown while activating Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator -&gt; Microsoft.AspNetCore.Authorization.DefaultAuthorizationService -&gt; Microsoft.AspNetCore.Authorization.DefaultAuthorizationHandlerProvider -&gt; λ:Microsoft.AspNetCore.Authorization.IAuthorizationHandler[] -&gt; InventoryManagement.API.Authorization.Decision.DecisionRequirementHandler.
  ---&gt; Autofac.Core.DependencyResolutionException: None of the constructors found with &#39;Autofac.Core.Activators.Reflection.DefaultConstructorFinder&#39; on type &#39;InventoryManagement.API.Authorization.Decision.DecisionRequirementHandler&#39; can be invoked with the available services and parameters:
  Cannot resolve parameter &#39;Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor&#39; of constructor &#39;Void .ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.Extensions.Options.IOptionsMonitor`1[Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions])&#39;.

We should Register HttpContextAccessor and JwtBearerOptions to solve the issue.

builder.RegisterType&lt;HttpContextAccessor&gt;().As&lt;IHttpContextAccessor&gt;().SingleInstance(); 
builder.Register(c =&gt; c.Resolve&lt;IOptions&lt;JwtBearerOptions&gt;&gt;().Value).As&lt;JwtBearerOptions&gt;();

huangapple
  • 本文由 发表于 2023年2月24日 13:30:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75552917.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定