英文:
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 参数。
你可以尝试以下步骤来解决这个问题:
- 确保你已正确注册 IHttpContextAccessor 服务。通常,你需要在 Startup.cs 文件中的 ConfigureServices 方法中添加以下代码:
services.AddHttpContextAccessor();
这会确保 IHttpContextAccessor 可以被解析并注入到 DecisionRequirementHandler 类中。
-
确保你的 Autofac 配置正确。确保 AutofacServiceProviderFactory 正确配置,并且容器已经正确加载了你的 RepositoryServiceModule。
-
确保你的依赖项包已经正确安装,特别是 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'。
我们应该注册 HttpContextAccessor
和 JwtBearerOptions
来解决这个问题。
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 -> 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])'.
We should Register HttpContextAccessor
and JwtBearerOptions
to solve the issue.
builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
builder.Register(c => c.Resolve<IOptions<JwtBearerOptions>>().Value).As<JwtBearerOptions>();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论