Docker 和身份服务器 4、api、angular:无法分配请求的地址

Posted

技术标签:

【中文标题】Docker 和身份服务器 4、api、angular:无法分配请求的地址【英文标题】:Docker and identity server 4, api, angular : Cannot assign requested address 【发布时间】:2019-11-17 19:39:16 【问题描述】:

我在 macos 中设置了一个 docker(但应该可以在任何环境中工作):

1) 在容器中运行的身份服务器 4

启动设置:

"MacTest": 
  "commandName": "Project",
  "environmentVariables": 
    "ASPNETCORE_HTTPS_PORT": "44000",
    "ASPNETCORE_ENVIRONMENT": "MacTest"
  ,
  "applicationUrl": "https://0.0.0.0:44000" 

dockerfile(dockerfile-idp):

ENTRYPOINT ["dotnet", "run", "--launch-profile", "MacTest"]

作曲家:

identityserver:
image: idp
build: 
  context: .
  dockerfile: ./docker/dockerfile-idp
ports:
 - "9000:9000"
 - "44000:44000"
volumes:
 - .:/idp

2) APIsource 在容器上运行的身份服务器上进行身份验证: 启动设置:

"MacTest": 
  "commandName": "Project",
  "environmentVariables": 
    "ASPNETCORE_ENVIRONMENT": "MacLocalTest",
    "ASPNETCORE_HTTPS_PORT": 44100
  ,
  "applicationUrl": "https://0.0.0.0:44100"

dockerfile(dockerfile-api):

ENTRYPOINT ["dotnet", "run", "--launch-profile", "MacTest"]

作曲家:

  api:
image: api
build: 
  context: .
  dockerfile: ./docker/dockerfile-api
ports:
 - "9100:9100"
 - "44100:44100"
volumes:
 - .:/api 

3) 在其他容器上运行的 Angular 应用程序

问题: Angular 登录页面可以连接到身份服务器,并且可以获取有效的令牌... OK

它可以Api和检索公共数据... OK

但是它不能使用 Authorize 调用受保护的方法。我开始相信 api 尝试从身份服务器对自己进行身份验证,但由于某种原因它无法访问服务器。

[HttpGet("info")]
[AppAuthorize]   => THIS NOT WORK 
public IActionResult Info()

...
 

错误:

System.Net.Sockets.SocketException (99): Cannot assign requested address
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
HttpRequestException: Cannot assign requested address
System.Net.Http.ConnectHelper.ConnectAsync(string host, int port, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask<ValueTuple<HttpConnection, HttpResponseMessage>> creationTask)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, bool doRequestAuth, CancellationToken cancellationToken)
System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task<HttpResponseMessage> sendTask, HttpRequestMessage request, CancellationTokenSource cts, bool disposeCts)
Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)

Show raw exception details
System.Net.Http.HttpRequestException: Cannot assign requested address ---> System.Net.Sockets.SocketException: Cannot assign requested address
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
IOException: IDX20804: Unable to retrieve document from: 'https://localhost:44000/.well-known/openid-configuration'.
Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)
Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel)
Microsoft.IdentityModel.Protocols.ConfigurationManager<T>.GetConfigurationAsync(CancellationToken cancel)

Show raw exception details
System.IO.IOException: IDX20804: Unable to retrieve document from: 'https://localhost:44000/.well-known/openid-configuration'. ---> System.Net.Http.HttpRequestException: Cannot assign requested address ---> System.Net.Sockets.SocketException: Cannot assign requested address
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   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)
InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://localhost:44000/.well-known/openid-configuration'.
Microsoft.IdentityModel.Protocols.ConfigurationManager<T>.GetConfigurationAsync(CancellationToken cancel)
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.AuthenticationHandler<TOptions>.AuthenticateAsync()
Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, string scheme)
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler.HandleAuthenticateAsync() in C:\local\identity\server4\AccessTokenValidation\src\IdentityServerAuthenticationHandler.cs
Microsoft.AspNetCore.Authentication.AuthenticationHandler<TOptions>.AuthenticateAsync()
Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, string scheme)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.InvokeCore(HttpContext context)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

我正在尝试设置一个新的湿工作设置,但非常具有挑战性,我什至不知道网络是否有问题。有人可以帮忙吗?

谢谢你

【问题讨论】:

当第一次在 API 端调用 auth 中间件时,它会尝试从权限提供者(在本例中为您的 IDS4)获取元数据文档,因此它需要能够解析和连接到发行人 uri),在您的情况下,它似乎无法做到。 【参考方案1】:

所以你已经展示了很多 IdentityServer 的设置,但是你没有展示你的 API 的很多设置。

我最好的选择是以下两个之一:

1) 您尚未安装中间件并在您的 API 上正确设置它。因此 API 无法对不记名令牌做任何事情。

来自文档:Securing APIs

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    
        // base-address of your identityserver
        options.Authority = "https://demo.identityserver.io";

        // name of the API resource
        options.Audience = "api1";
    );

您需要添加权限(即 IdentityServer),然后您需要告诉 IdentityServer 它将保护 API。所有这些都可以在文档中找到。

2) 两个 docker 容器之间的网络不允许它们相互通信。

尝试使用 SSH 连接到 API 的 docker 容器(谷歌如何做到这一点)。尝试使用 cURL 调用身份服务器,看看是否可以从 API 的 Docker 容器内部访问 IP。如果你不能这样做,你需要在两个 docker 容器之间建立一个共享的内部网络。

【讨论】:

【参考方案2】:

感谢您的帮助。我想我设法通过了这个错误,现在又出现了另一个错误:

AuthenticationException:远程证书根据验证程序无效。

身份服务器启动:

services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            
                options.Authority = "https://localhost:44000";
                options.SupportedTokens = SupportedTokens.Jwt;
                // Note: Set to true in production
                options.RequireHttpsMetadata = true;
                options.ApiName = "api";
            );

API 启动:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        services.AddAuthentication(options =>
        
            options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        )
        .AddIdentityServerAuthentication(options =>
        
            options.Authority = "https://idp:44000";
            options.RequireHttpsMetadata = true;
            options.ApiName = "api";
        );

我找不到任何解决方案。你觉得有证书问题吗?

【讨论】:

嘿 Cern。抱歉,我没有看到后续问题。下次你想问一个后续问题时,你应该在 *** 上问另一个问题。如果你想要我的意见,然后在上面的 cmets 中用新问题 ping 我。这样,您就可以保留每个页面关于 一个 的问题。这让其他人更容易找到问题的答案。【参考方案3】:

我解决了我的问题(还没有使用 https),但正常的工作流程可以正常工作。

如果有人遇到同样的问题,我推荐这篇文章: Exactly what I did but I have an angular app in plus

对于 https,我建议: To get it work with https

这是相当具有挑战性的,还有工作要做,但至少完成了这个令人讨厌的步骤。

【讨论】:

以上是关于Docker 和身份服务器 4、api、angular:无法分配请求的地址的主要内容,如果未能解决你的问题,请参考以下文章

使用外部 WCF 服务时,在 docker 内运行的 Dotnet 核心 Web api 无法进行身份验证

未通过 ZAP API 扫描 docker 映像进行身份验证

使用身份服务器 4 保护 asp.net web api 2 项目

.net 4.6 web api2 401 未经授权使用身份服务器 4

HADOOP docker:hdfs权限

AngularJS API