【问题标题】:Unable to resolve service for type 'FlexibleConfiguration.Abstractions.IConfiguration' in .Net Core 3.0 Web API无法解析 .Net Core 3.0 Web API 中类型“FlexibleConfiguration.Abstractions.IConfiguration”的服务
【发布时间】:2020-03-26 14:10:09
【问题描述】:

我正在尝试将身份验证和基于策略的授权添加到 .net core 3 Web API。但是,添加策略后出现一个奇怪的错误。我对.net 很陌生。我无法确定究竟是什么导致了这个错误,它(显然)是在我将策略添加到我的应用程序之后开始的,并且在添加它之前工作得很好,我不知道为什么它不工作。我将服务注册为单例并尝试将其作为瞬态,但仍然没有运气。

InvalidOperationException:尝试激活“actualizer.Security.claims.transformation.UserTransformer”时无法解析“FlexibleConfiguration.Abstractions.IConfiguration”类型的服务。

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);
    }
}

【问题讨论】:

    标签: c# .net asp.net-core asp.net-web-api .net-3.0


    【解决方案1】:

    错误发生在您的UserTransformer 类中,因为您使用FlexibleConfiguration.Abstractions 注入IConfiguration config 而您没有注册它。

    我对这个包不熟悉,如果你想使用它,你需要和所有者确认它是否支持asp.net core 3.0。

    最简单的方法是在UserTransformer.cs 中使用using Microsoft.Extensions.Configuration; 而不是using FlexibleConfiguration.Abstractions,就像您在startup.cs 中所做的那样。

    或者只是删除构造函数参数中的IConfiguration config,因为您根本没有在代码中使用它。

    【讨论】:

    • 这当然是问题所在,我认为 Visual Studio 试图提供帮助并添加了 using 语句,这或多或少是样板文件。原来我的 oktaclient 服务也注册了错误,这导致了其他奇怪的错误。感谢您的时间和帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 2021-12-25
    • 2020-07-01
    相关资源
    最近更新 更多