无法解析 .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,因为您在代码中根本没有使用它。