【问题标题】:System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String' with .NET 5System.InvalidOperationException:IDX20803:无法从 .NET 5 的“System.String”获取配置
【发布时间】:2022-01-15 14:34:15
【问题描述】:

我一直在实施 IdentityServer4 来为我的 React 应用程序提供授权。我有这个在我的本地开发环境中工作,但在 Windows Server 2016 中部署到 IIS 后遇到问题。我能够通过 /connect/token 端点生成访问令牌,但是当我尝试使用访问受保护的 API 时令牌我得到以下异常:

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'.
 ---> System.IO.IOException: IDX20804: Unable to retrieve document from: 'System.String'.
 ---> System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (dev-drydata-auth.universal-compliance.com:443)
 ---> System.Net.Sockets.SocketException (10060): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
   at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|283_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.DefaultConnectAsync(SocketsHttpConnectionContext context, CancellationToken cancellationToken)
   at System.Net.Http.ConnectHelper.ConnectAsync(Func`3 callback, DnsEndPoint endPoint, HttpRequestMessage requestMessage, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.ConnectAsync(Func`3 callback, DnsEndPoint endPoint, HttpRequestMessage requestMessage, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
   at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
   at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at NSwag.AspNetCore.Middlewares.SwaggerUiIndexMiddleware.Invoke(HttpContext context)
   at NSwag.AspNetCore.Middlewares.RedirectToIndexMiddleware.Invoke(HttpContext context)
   at NSwag.AspNetCore.Middlewares.OpenApiDocumentMiddleware.Invoke(HttpContext context)
   at Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
   at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()

我的ConfigureServices如下:

public void ConfigureServices(IServiceCollection services)
{
    ConfigureDryDataServices(services);

    services.AddControllersWithViews();

    services.AddCors(options =>
    {
        options.AddPolicy("AllOrigins",
        builder =>
        {
            builder.AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowAnyOrigin();

        });
    });
    services.AddScoped<IClaimsTransformation, WebAppCalimsTransformation>();
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(o =>
    {
        o.Authority = Configuration.GetValue<string>("AppSettings:Auth:ServerUrl");
        o.Audience = Configuration.GetValue<string>("AppSettings:Auth:Audience");
        o.RequireHttpsMetadata = false;
        o.Events = new JwtBearerEvents
        {
            OnTokenValidated = context =>
            {
                if (context.SecurityToken is JwtSecurityToken accessToken && context.Principal.Identity is ClaimsIdentity identity)
                {
                    identity.AddClaim(new Claim("access_token", accessToken.RawData));
                }

                return Task.CompletedTask;
            }
        };
    });

    services.AddAuthorization(options =>
    {
        options.AddPolicy("ApiReader", policy => policy.RequireClaim("scope", "my_api_software"));
        options.AddPolicy("admin", policy => policy.RequireClaim(ClaimTypes.Role, "admin"));
        options.AddPolicy("user", policy => policy.RequireClaim(ClaimTypes.Role, "user"));
    });

    services.AddHttpClient("Auth", config =>
    {
        config.BaseAddress = new Uri(Configuration.GetValue<string>("AppSettings:Auth:ServerUrl"));
    });

    // In production, the React files will be served from this directory
    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "ClientApp/build";
    });


    services.AddSwaggerDocument(config => {
        config.OperationProcessors.Add(new OperationSecurityScopeProcessor("JWT token"));
        config.AddSecurity("JWT token", new OpenApiSecurityScheme
        {
            Type = OpenApiSecuritySchemeType.ApiKey,
            Name = "Authorization",
            Description = "Copy 'Bearer ' + valid JWT token into field",
            In = OpenApiSecurityApiKeyLocation.Header
        });
        config.PostProcess = (document) =>
        {
            document.Info.Version = "v1";
            document.Info.Title = "My API API";
            document.Info.Description = "ASP.NET 5.0 My API";
        };
    });
}

在我的电脑中部署本地 IIS 时也可以正常工作

【问题讨论】:

  • 堆栈跟踪表明您的 OpenId 配置发现端点 (.well-known/openid-configuration) 不可访问
  • @AndrewSilver,感谢您为我指明了正确的方向。似乎我也无法在服务器内部的浏览器中访问 OpenId 配置发现端点。我将端点添加到 Internet Explorer 的受信任站点列表中,但仍然阻止它。我认为服务器内部应该有一些配置来授予服务器管理员访问权限。

标签: asp.net-web-api jwt identityserver4 .net-5


【解决方案1】:

问题是 API 无法从您的部署中访问您的 IdentityServer,如下代码中所定义:

  }).AddJwtBearer(o =>
    {
        o.Authority = Configuration.GetValue<string>("AppSettings:Auth:ServerUrl");
  

因此,您需要通过网络/dns 执行此操作,以确保 API 中的权限实际上可以从您的服务器中访问。即使它们都可以从您的浏览器访问,并不意味着 API 可以从服务器端的本地网络中访问您的 IdentityServer。

【讨论】:

  • 您说得对,看来我也无法在服务器内部的浏览器中访问 OpenId 配置发现端点。我将端点添加到 Internet Explorer 的受信任站点列表中,但仍然阻止它。
  • 它也可以是路由器/DNS 事物,路由器会阻止到“自身”的流量。一种选择是对服务之间的流量使用内部服务名称,对公共流量使用公共名称。或者,您可以在主机文件中硬编码您的 IS 域的 IP 地址。取决于您的部署设置。但这是一个常见问题。
猜你喜欢
  • 2022-11-08
  • 2021-04-29
  • 2021-09-10
  • 2022-07-04
  • 1970-01-01
  • 2021-07-01
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多