【发布时间】:2022-09-24 18:23:39
【问题描述】:
好的,所以我已经为此苦苦挣扎了好几天。我已经阅读了我可以在 GitHub、Microsoft 等网站上找到的所有帖子。我尝试过的所有解决方案都不起作用。
系统架构:
- 使用 Duende BFF 安全框架的 Blazor .NET WASM ASP.NET Core 托管应用程序
- Duende 身份服务器外部实例
- Ocelot API 网关
- .NET6 远程 Web API
- 所有应用程序都作为单独的域部署到服务器间共享 IIS 服务器
问题: 调用 GET 方法时,一切都按预期工作。响应标头按照解决方案中的设置返回。在开发中调用任何方法时,一切都按预期工作。在生产环境中调用 PUT 或 DELETE 时,调用会立即失败,并出现 405 Method Not Allowed。
尝试的解决方案:
- 向 Api 网关添加了 CORS 策略以允许任何标头/方法。检查日志。没有呼叫到达网关。这告诉我它在客户端和服务器之间失败。
- 更新了服务器以使用 SetIsOriginAllowed(origin => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials() 添加 CORS 策略
- 使用以下部分更新了 web.config:
<security>
<requestFiltering removeServerHeader=\"true\">
<verbs allowUnlisted=\"true\">
<add verb=\"POST\" allowed=\"true\"/>
<add verb=\"PUT\" allowed=\"true\"/>
<add verb=\"DELETE\" allowed=\"true\"/>
</verbs>
</requestFiltering>
</security>
- 使用 context.Response.Headers.Allow = \"GET, POST, DELETE, PUT, OPTIONS\" 更新了服务器中的自定义安全标头;
我附上了两张图片,显示了 GET 和 PUT 的响应标头。 GET 看起来符合预期。 PUT 不包含我设置的任何标题。这是我的服务器 Program.cs:
using System.Net.Http.Headers;
using Azure.Identity;
using JMS.UI.Server.Extensions;
using JMS.UI.Server.Helpers;
using JMS.UI.Server.Settings;
using JMS.UI.Server.Static;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.Primitives;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
// Add Azure Key Vault
var keyVaultEndpoint = new Uri(HIDDEN);
builder.Configuration.AddAzureKeyVault(HIDDEN);
// Add identity services
var idsSettings = new IdentityServerSettings { ClientPassword = builder.Configuration[\"HIDDEN\"] };
#if DEBUG
idsSettings.DiscoveryUrl = \"https://localhost:7102\";
idsSettings.ClientName = \"HIDDEN\";
#else
idsSettings.DiscoveryUrl = \"HIDDEN\";
idsSettings.ClientName = \"HIDDEN\";
#endif
builder.Services.AddControllers();
builder.Services.AddRazorPages();
builder.Services.AddBff();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultSignOutScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.Cookie.SameSite = SameSiteMode.Lax;
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = idsSettings.DiscoveryUrl;
options.ClientId = idsSettings.ClientName;
options.ClientSecret = idsSettings.ClientPassword;
options.ResponseType = OpenIdConnectResponseType.Code;
options.ResponseMode = OpenIdConnectResponseMode.Query;
options.MapInboundClaims = false;
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.UsePkce = true;
options.Scope.Clear();
options.Scope.Add(\"JMS\");
options.Scope.Add(\"openid\");
options.Scope.Add(\"profile\");
options.Scope.Add(\"email\");
options.Scope.Add(\"offline_access\");
});
// Add services to the container.
builder.Services.AddAutoMapper(typeof(AutomapperProfiles).Assembly);
builder.Services.AddSettingsServiceConfigurations(builder.Configuration);
builder.Services.AddServicesInjectors();
#if DEBUG
ApiEndpoints.ApiBaseUrl = new Uri(\"https://localhost:7200\");
#else
ApiEndpoints.ApiBaseUrl = new Uri(\"HIDDEN\");
#endif
builder.Services.AddHttpClient(\"JmsClient\", options =>
{
options.BaseAddress = ApiEndpoints.ApiBaseUrl;
options.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { MaxAge = TimeSpan.FromSeconds(2592000) };
}).AddUserAccessTokenHandler();
builder.Services.AddCors(options =>
{
options.AddPolicy(\"JmsPolicy\", b => b.SetIsOriginAllowed(origin => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials());
});
builder.Services.AddHttpContextAccessor();
builder.Logging.SetMinimumLevel(LogLevel.Error);
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler(\"/Error\");
app.Use(async (context, next) =>
{
context.Response.Headers.XXSSProtection = \"1; mode=block\";
context.Response.Headers.XFrameOptions = \"SAMEORIGIN\";
context.Response.Headers.XContentTypeOptions = \"nosniff\";
context.Response.Headers.Add(\"Referrer-Policy\", \"strict-origin-when-cross-origin\");
context.Response.Headers.Allow = \"GET, POST, DELETE, PUT, OPTIONS\";
context.Response.Headers.ContentSecurityPolicy =
\"default-src \'self\'; \" +
\"frame-ancestors \'none\'; \" +
\"font-src \'self\' https://fonts.googleapis.com https://fonts.gstatic.com https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; \" +
\"style-src \'self\' \'unsafe-inline\' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://fonts.googleapis.com https://fonts.gstatic.com; \" +
\"script-src \'self\' \'unsafe-eval\' \'unsafe-inline\' https://cdn.jsdelivr.net https://use.fontawesome.com https://www.google.com https://maps.googleapis.com https://www.gstatic.com; \" +
\"img-src \'self\' data: https://www.google.com https://maps.googleapis.com https://www.gstatic.com https://maps.gstatic.com; \" +
\"connect-src \'self\' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://use.fontawesome.com https://maps.googleapis.com https://www.google.com https://fonts.googleapis.com https://fonts.gstatic.com https://www.gstatic.com; \" +
\"frame-src https://www.google.com https://maps.googleapis.com https://www.gstatic.com;\";
await next();
});
}
app.UseCors(\"JmsPolicy\");
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseBff();
app.UseAuthorization();
app.MapBffManagementEndpoints();
app.MapRazorPages();
app.MapControllers()
.RequireAuthorization()
.AsBffApiEndpoint();
app.MapFallbackToFile(\"index.html\");
app.Run();
标签: asp.net asp.net-identity http-status-code-405 ocelot duende-identity-server