将 signalR 通知中心部署到 IIS 时出现 CORS 错误
CORS errors when deploying signalR notification Hub to IIS
我的 signalR Hub 可以 运行 在安全端口 44311 上的 VS2019 调试模式下正常,但是一旦我将它发布到我的开发箱上的本地 IIS,../hub/negotiate
就会失败并显示 CORS policy
异常。
ex.在调试模式下,IIS托盘
signalr Hub 正常启动:
现在进入我的本地 Window 10 IIS 设置,我在其中部署了 signalR Hub 项目:
- 我设置了 https 绑定
- 我成功设置了 SSL 证书,并设置了需要 SSL 复选框:
- 我重新启动我的 IIS 网站,并浏览 44311 进行测试
但果然,我的应用无法连接到 HUB:
Access to XMLHttpRequest at 'https://localhost:44311/hub/negotiate?negotiateVersion=1' from origin 'http://localhost:4200' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
POST https://localhost:44311/hub/negotiate?negotiateVersion=1 net::ERR_FAILED
然而在我的代码中我注入了CORS
:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NotificationHub.Hubs;
namespace NotificationHub
{
public class Startup
{
readonly string MyAllowedSpecificOrigins = "_myAllowedSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowedSpecificOrigins,
builder => {
builder.WithOrigins("https://localhost:4200", "localhost:4200")
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true);
}
);
});
services.AddSignalR(hubOptions => {
hubOptions.EnableDetailedErrors = true;
hubOptions.KeepAliveInterval = System.TimeSpan.FromMinutes(1000);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowedSpecificOrigins);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<Notifications>("/hub", options => {
options.Transports = HttpTransportType.WebSockets | HttpTransportType.LongPolling;
});
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Notification HUB has started!");
});
});
}
}
}
目前我不确定这是编码问题(即未正确设置 CORS)还是部署问题。
感谢帮助。
谢谢。
更新
根据下面的建议答案,我的 CORS 问题在部署到 IIS 时得到解决:
- 为 IIS 安装 cors:https://www.iis.net/downloads/microsoft/iis-cors-module
- 添加以下
<customHeaders>
到 web.config
但是,我在 IIS 部署模式下仍然无法成功连接到集线器 (http://localhost:55271/hub/negotiate?negotiateVersion=1 throws 404 not found
);但是调试工作正常。
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost:4200" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Request-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag,XMLHttpRequest,x-requested-with" />
<add name="Access-Control-Allow-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag,XMLHttpRequest,x-requested-with" />
<add name="Access-Control-Request-Method" value="GET,POST,HEAD,OPTIONS" />
</customHeaders>
</httpProtocol>
确保您启用了 iis .net 功能。在 iis 中为站点启用目录浏览:
1)启动 IIS 管理器。
2)在 IIS 管理器中,展开服务器名称,展开网站,然后 select 网站。
3)在“功能”视图中,双击“目录浏览”。
4) 在“操作”窗格中,单击“启用”。
在 web.config 文件中添加以下代码:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://my-external-app-domain.com" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Request-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag" />
<add name="Access-Control-Request-Method" value="GET,POST,HEAD,OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
使用 web 平台安装程序或从下面在 iis 中安装 cors 模块 link:
https://www.iis.net/downloads/microsoft/iis-cors-module
更新:
在下面添加到 web.config:
HttpRequest,x-requested-with 在“Access-Control-Request-Headers”中都需要。此外,我插入了 header name="Access-Control-Allow-Headers" ,其值与 Request-Headers 相同。
我的 signalR Hub 可以 运行 在安全端口 44311 上的 VS2019 调试模式下正常,但是一旦我将它发布到我的开发箱上的本地 IIS,../hub/negotiate
就会失败并显示 CORS policy
异常。
ex.在调试模式下,IIS托盘
signalr Hub 正常启动:
现在进入我的本地 Window 10 IIS 设置,我在其中部署了 signalR Hub 项目:
- 我设置了 https 绑定
- 我成功设置了 SSL 证书,并设置了需要 SSL 复选框:
- 我重新启动我的 IIS 网站,并浏览 44311 进行测试
但果然,我的应用无法连接到 HUB:
Access to XMLHttpRequest at 'https://localhost:44311/hub/negotiate?negotiateVersion=1' from origin 'http://localhost:4200' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
POST https://localhost:44311/hub/negotiate?negotiateVersion=1 net::ERR_FAILED
然而在我的代码中我注入了CORS
:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NotificationHub.Hubs;
namespace NotificationHub
{
public class Startup
{
readonly string MyAllowedSpecificOrigins = "_myAllowedSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowedSpecificOrigins,
builder => {
builder.WithOrigins("https://localhost:4200", "localhost:4200")
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true);
}
);
});
services.AddSignalR(hubOptions => {
hubOptions.EnableDetailedErrors = true;
hubOptions.KeepAliveInterval = System.TimeSpan.FromMinutes(1000);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowedSpecificOrigins);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<Notifications>("/hub", options => {
options.Transports = HttpTransportType.WebSockets | HttpTransportType.LongPolling;
});
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Notification HUB has started!");
});
});
}
}
}
目前我不确定这是编码问题(即未正确设置 CORS)还是部署问题。
感谢帮助。
谢谢。
更新
根据下面的建议答案,我的 CORS 问题在部署到 IIS 时得到解决:
- 为 IIS 安装 cors:https://www.iis.net/downloads/microsoft/iis-cors-module
- 添加以下
<customHeaders>
到 web.config
但是,我在 IIS 部署模式下仍然无法成功连接到集线器 (http://localhost:55271/hub/negotiate?negotiateVersion=1 throws 404 not found
);但是调试工作正常。
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost:4200" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Request-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag,XMLHttpRequest,x-requested-with" />
<add name="Access-Control-Allow-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag,XMLHttpRequest,x-requested-with" />
<add name="Access-Control-Request-Method" value="GET,POST,HEAD,OPTIONS" />
</customHeaders>
</httpProtocol>
确保您启用了 iis .net 功能。在 iis 中为站点启用目录浏览:
1)启动 IIS 管理器。
2)在 IIS 管理器中,展开服务器名称,展开网站,然后 select 网站。
3)在“功能”视图中,双击“目录浏览”。
4) 在“操作”窗格中,单击“启用”。
在 web.config 文件中添加以下代码:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://my-external-app-domain.com" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Request-Headers" value="User-Agent,Content-Type,Authorization,X-RequestDigest,X-ClientService-ClientTag" />
<add name="Access-Control-Request-Method" value="GET,POST,HEAD,OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
使用 web 平台安装程序或从下面在 iis 中安装 cors 模块 link:
https://www.iis.net/downloads/microsoft/iis-cors-module
更新:
在下面添加到 web.config:
HttpRequest,x-requested-with 在“Access-Control-Request-Headers”中都需要。此外,我插入了 header name="Access-Control-Allow-Headers" ,其值与 Request-Headers 相同。