我正在致力于容器化 ASP.NET Web API。我的项目位于 .NET 8 中,API 在 Visual Studio 和 Azure 中运行良好。我可以启动 API 并使用从 Entra 获得的 JWT 调用它,一切都没有问题。我在API上配置授权如下:
// Add authentication services
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
builder.Configuration.Bind("AzureAd", options);
options.Authority = $"{builder.Configuration["AzureAd:Instance"]}{builder.Configuration["AzureAd:TenantId"]}/v2.0";
// The valid audiences are both the Client ID(options.Audience) and api://{ClientID}
options.TokenValidationParameters.ValidAudiences =
[
builder.Configuration["AzureAd:ClientId"],
$"api://{builder.Configuration["AzureAd:ClientId"]}",
];
// Valid issuers here:
options.TokenValidationParameters.ValidIssuers =
[
$"https://sts.windows.net/{builder.Configuration["AzureAd:TenantId"]}/",
$"{builder.Configuration["AzureAd:Instance"]}{builder.Configuration["AzureAd:TenantId"]}/",
$"https://login.microsoftonline.com/{builder.Configuration["AzureAd:TenantId"]}/v2.0"
];
});
到目前为止一切顺利。然后我尝试将其容器化。我使用 Visual Studio 工具添加 docker 支持,包括 docker 文件,经过一些实验后,它将运行并启动。我可以调用 API 中不需要授权的方法。但是,当我尝试使用 [Authorize] 属性调用控制器中的方法时,它会中断。响应是 401 Unauthorized,返回的标头为:
content-length: 0
date: Tue,16 Apr 2024 19:17:36 GMT
server: Kestrel
www-authenticate: Bearer error="invalid_token",error_description="The signature key was not found"
请注意,如果我将其作为本地运行的 API 启动,则同样的代码可以正常运行。在容器中启动它,不起作用。
我当前的假设是,当 JWT 验证代码运行时,它尝试从权威机构获取签名密钥并失败。它在本地启动时可以工作,因为允许对签名密钥的传出请求并且工作正常,但是当它在容器中运行时,容器不允许该传出请求。
为了测试这一点,我向控制器添加了一个方法,该方法执行以下操作:
var client = new HttpClient();
client.BaseAddress = new Uri("https://www.microsoft.com/");
var resp = await client.GetAsync(string.Empty);
html = await resp.Content.ReadAsStringAsync();
只是为了看看容器是否可以发出any传出请求,any。它失败并出现以下错误:
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot
我不知道如何解决这个问题。我不想在容器中安装证书或密钥,因为如果该证书发生变化怎么办?这应该可以在运行时获得。
有没有办法允许我丢失的容器代码发出 HTTP 请求?
谢谢,
您可以像下面一样忽略证书验证;
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>{return true;};
var client = new HttpClient(httpClientHandler));
...