我正在尝试将身份验证和基于策略的授权添加到 .net core 3 Web API。但是,添加策略后出现一个奇怪的错误。我对.net 很陌生。我无法确定究竟是什么导致了这个错误,它(显然)是在我将策略添加到我的应用程序之后开始的,并且在添加它之前工作得很好,我不知道为什么它不工作。我将服务注册为单例并将其尝试为瞬态,但仍然没有运气。
InvalidOperationException:尝试激活“actualizer.Security.claims.transformation.UserTransformer”时无法解析“FlexibleConfiguration.Abstractions.IConfiguration”类型的服务。
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(类型 serviceType,类型 implementationType,CallSiteChain callSiteChain,ParameterInfo[] 参数,bool throwIfCallSiteNotFound)
启动.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();
}
}
}
用户变压器.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;
}
}
}
索赔.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);
}
}