无法解析 .Net Core 3.0 Web API 中类型 'FlexibleConfiguration.Abstractions.IConfiguration' 的服务
Unable to resolve service for type 'FlexibleConfiguration.Abstractions.IConfiguration' in .Net Core 3.0 Web API
我正在尝试向 .net core 3 Web 添加身份验证和基于策略的授权 API。但是,添加策略后出现奇怪的错误。我对 .net 很陌生。我无法确定到底是什么导致了这个错误,它(显然)是在我将策略添加到我的应用程序之后开始的,并且在添加它之前工作得很好而且我无法弄清楚为什么它不起作用。我将该服务注册为单例并尝试将其作为 Transient,但仍然没有成功。
InvalidOperationException: Unable to resolve service for type 'FlexibleConfiguration.Abstractions.IConfiguration' while attempting to activate 'actualizer.Security.claims.transformation.UserTransformer'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Okta.AspNetCore;
using Microsoft.OpenApi.Models;
using Okta.Sdk;
using Okta.Sdk.Configuration;
using Microsoft.AspNetCore.Authentication;
using actualizer.Security.claims;
using actualizer.Security.claims.transformation;
namespace actualizer {
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddMvc(option => option.EnableEndpointRouting = false);
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Actualizer", Version = "v1" });
});
var client = new OktaClient(new OktaClientConfiguration {
OktaDomain = "https://dev-xxxxxx.okta.com",
Token = "xxxxxxxxxxxxxxxx"
});
services.AddSingleton<IOktaClient, OktaClient>();
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
})
.AddOktaWebApi(new OktaWebApiOptions() {
OktaDomain = "xxxxxxxxxxx"
});
services.AddSingleton<IClaimsTransformation, UserTransformer>();
services.AddAuthorization(options => {
options.AddPolicy("CanMakeAnalyticsRequests", policy => policy.RequireClaim("CanMakeAnalyticsRequests"));
});
services.AddCors(options => {
options.AddPolicy("VueCorsPolicy", builder => {
builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.WithOrigins("http://localhost:8080");
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostEnvironment env) {
//Swagger MIddleware
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Actualizer");
c.RoutePrefix = string.Empty;
});
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseHsts();
}
app.UseCors("VueCorsPolicy");
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
}
}
UserTransformer.cs
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using actualizer.Policy;
using FlexibleConfiguration.Abstractions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Okta.Sdk;
namespace actualizer.Security.claims.transformation {
public class UserTransformer : IClaimsTransformation {
private readonly IOktaClient _oktaClient;
IHttpContextAccessor _httpContextAccessor;
public UserTransformer(IConfiguration config, IHttpContextAccessor httpContextAccessor, IOktaClient oktaClient) {
_httpContextAccessor = httpContextAccessor;
this._oktaClient = oktaClient;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal p) {
var claimsIdentity = p.Identity as ClaimsIdentity;
string _CanMakeAnalyticsRequests = "CanMakeAnalyticsRequests";
var uid = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "uid").Value;
var user = await _oktaClient.Users.GetUserAsync(uid);
var permissions = user.Profile["permissions"];
if (permissions.ToString() == _CanMakeAnalyticsRequests) {
claimsIdentity.AddClaim(new Claim(Claims.CanMakeAnalyticsRequests, string.Empty));
}
return p;
}
}
}
CanMakeAnalyticsRequests.cs
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
namespace actualizer.Policy.Policies {
public class CanMakeAnalyticsRequests : AuthorizationHandler<CanMakeAnalyticsRequests>, IAuthorizationRequirement {
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanMakeAnalyticsRequests requirement) {
if (context.User.Claims.Any(c => c.Type == Claims.CanMakeAnalyticsRequests)) {
context.Succeed(requirement);
} else {
Console.WriteLine($"{context.User.Claims} tried to call analytics api");
context.Fail();
}
return Task.CompletedTask;
}
}
}
claims.cs
using System;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
namespace actualizer.Policy {
public class Claims {
public const string CanMakeAnalyticsRequests = nameof(CanMakeAnalyticsRequests);
}
}
错误发生在你的 UserTransformer
class 中,因为你使用 FlexibleConfiguration.Abstractions
作为注入的 IConfiguration config
而你没有注册它。
我对这个包不熟悉,如果你想使用它,你需要向所有者确认它是否支持asp.net core 3.0。
最简单的方法是在 UserTransformer.cs
中使用 using Microsoft.Extensions.Configuration;
而不是 using FlexibleConfiguration.Abstractions
,就像您在 startup.cs
中所做的那样。
或者只是删除构造函数参数中的 IConfiguration config
,因为您在代码中根本没有使用它。
我正在尝试向 .net core 3 Web 添加身份验证和基于策略的授权 API。但是,添加策略后出现奇怪的错误。我对 .net 很陌生。我无法确定到底是什么导致了这个错误,它(显然)是在我将策略添加到我的应用程序之后开始的,并且在添加它之前工作得很好而且我无法弄清楚为什么它不起作用。我将该服务注册为单例并尝试将其作为 Transient,但仍然没有成功。
InvalidOperationException: Unable to resolve service for type 'FlexibleConfiguration.Abstractions.IConfiguration' while attempting to activate 'actualizer.Security.claims.transformation.UserTransformer'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Okta.AspNetCore;
using Microsoft.OpenApi.Models;
using Okta.Sdk;
using Okta.Sdk.Configuration;
using Microsoft.AspNetCore.Authentication;
using actualizer.Security.claims;
using actualizer.Security.claims.transformation;
namespace actualizer {
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddMvc(option => option.EnableEndpointRouting = false);
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Actualizer", Version = "v1" });
});
var client = new OktaClient(new OktaClientConfiguration {
OktaDomain = "https://dev-xxxxxx.okta.com",
Token = "xxxxxxxxxxxxxxxx"
});
services.AddSingleton<IOktaClient, OktaClient>();
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
})
.AddOktaWebApi(new OktaWebApiOptions() {
OktaDomain = "xxxxxxxxxxx"
});
services.AddSingleton<IClaimsTransformation, UserTransformer>();
services.AddAuthorization(options => {
options.AddPolicy("CanMakeAnalyticsRequests", policy => policy.RequireClaim("CanMakeAnalyticsRequests"));
});
services.AddCors(options => {
options.AddPolicy("VueCorsPolicy", builder => {
builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.WithOrigins("http://localhost:8080");
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostEnvironment env) {
//Swagger MIddleware
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Actualizer");
c.RoutePrefix = string.Empty;
});
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseHsts();
}
app.UseCors("VueCorsPolicy");
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
}
}
UserTransformer.cs
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using actualizer.Policy;
using FlexibleConfiguration.Abstractions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Okta.Sdk;
namespace actualizer.Security.claims.transformation {
public class UserTransformer : IClaimsTransformation {
private readonly IOktaClient _oktaClient;
IHttpContextAccessor _httpContextAccessor;
public UserTransformer(IConfiguration config, IHttpContextAccessor httpContextAccessor, IOktaClient oktaClient) {
_httpContextAccessor = httpContextAccessor;
this._oktaClient = oktaClient;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal p) {
var claimsIdentity = p.Identity as ClaimsIdentity;
string _CanMakeAnalyticsRequests = "CanMakeAnalyticsRequests";
var uid = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "uid").Value;
var user = await _oktaClient.Users.GetUserAsync(uid);
var permissions = user.Profile["permissions"];
if (permissions.ToString() == _CanMakeAnalyticsRequests) {
claimsIdentity.AddClaim(new Claim(Claims.CanMakeAnalyticsRequests, string.Empty));
}
return p;
}
}
}
CanMakeAnalyticsRequests.cs
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
namespace actualizer.Policy.Policies {
public class CanMakeAnalyticsRequests : AuthorizationHandler<CanMakeAnalyticsRequests>, IAuthorizationRequirement {
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanMakeAnalyticsRequests requirement) {
if (context.User.Claims.Any(c => c.Type == Claims.CanMakeAnalyticsRequests)) {
context.Succeed(requirement);
} else {
Console.WriteLine($"{context.User.Claims} tried to call analytics api");
context.Fail();
}
return Task.CompletedTask;
}
}
}
claims.cs
using System;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
namespace actualizer.Policy {
public class Claims {
public const string CanMakeAnalyticsRequests = nameof(CanMakeAnalyticsRequests);
}
}
错误发生在你的 UserTransformer
class 中,因为你使用 FlexibleConfiguration.Abstractions
作为注入的 IConfiguration config
而你没有注册它。
我对这个包不熟悉,如果你想使用它,你需要向所有者确认它是否支持asp.net core 3.0。
最简单的方法是在 UserTransformer.cs
中使用 using Microsoft.Extensions.Configuration;
而不是 using FlexibleConfiguration.Abstractions
,就像您在 startup.cs
中所做的那样。
或者只是删除构造函数参数中的 IConfiguration config
,因为您在代码中根本没有使用它。