文章目录
- 背景
- 困难
- ~~*调用 UseCors*~~
- 解决办法
- 环境
- 错误信息
- 解决方式
- 部分代码
- 问题分析
背景
使用前后端分离技术,前端使用Vue,部署在独立的服务器上,后端接口部署在另外一个服务器上。
困难
网上找了一个多小时的SignalR的跨域问题,包括微软官网的一些说明都是这样的(下面这段在.net6中不好用)
https://learn.microsoft.com/zh-cn/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#crossdomain
调用 UseCors
以下代码片段演示如何在 SignalR 2 中实现跨域连接。
在 SignalR 2 中实现跨域请求
以下代码演示如何在 SignalR 2 项目中启用 CORS 或 JSONP。 此代码示例使用 Map
和 RunSignalR
而不是 MapSignalR
,以便 CORS 中间件仅针对需要 CORS 支持 (的 SignalR 请求运行,而不是针对 .) Map 中指定的 MapSignalR
路径上的所有流量运行,也可用于需要针对特定 URL 前缀运行的任何其他中间件,而不是针对整个应用程序运行。
**
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Owin;
namespace MyWebApplication
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Branch the pipeline here for requests that start with "/signalr"
app.Map("/signalr", map =>
{
// Setup the CORS middleware to run before SignalR.
// By default this will allow all origins. You can
// configure the set of origins and/or http verbs by
// providing a cors options with a different policy.
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
// You can enable JSONP by uncommenting line below.
// JSONP requests are insecure but some older browsers (and some
// versions of IE) require JSONP to work cross domain
// EnableJSONP = true
};
// Run the SignalR pipeline. We're not using MapSignalR
// since this branch already runs under the "/signalr"
// path.
map.RunSignalR(hubConfiguration);
});
}
}
}
备注
-
不要在代码中将 设置为jQuery.support.cors
true。SignalR 处理 CORS 的使用。 将 设置为jQuery.support.cors
true 会禁用 JSONP,因为它会导致 SignalR 假定浏览器支持 CORS。 -
连接到 localhost URL 时,Internet Explorer 10 不会将其视为跨域连接,因此即使尚未在服务器上启用跨域连接,应用程序也会在本地使用 IE 10。 -
有关将跨域连接与 Internet Explorer 9 配合使用的信息,请参阅 此 StackOverflow 线程。 -
有关将跨域连接与 Chrome 配合使用的信息,请参阅 此 StackOverflow 线程。 -
示例代码使用默认的“/signalr”URL 连接到 SignalR 服务。 有关如何指定其他基 URL 的信息,请参阅 ASP.NET SignalR 中心 API 指南 - 服务器 - /signalr URL。
解决办法
环境
- .net6
- webapi
- vue3
错误信息
Access to fetch at ‘https://localhost:6001/sr/warning_broadcast/negotiate?negotiateVersion=1’ from origin ‘http://localhost:8080’ 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. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
解决方式
添加跨域支持
app.UseCors(opt =>
{
//不要允许所有源,因为这样编译会报错
opt.WithOrigins("http://localhost:8080").AllowAnyHeader().AllowAnyMethod().AllowCredentials();
});
部分代码
var app = builder.Build();
// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
//{
app.UseSwagger();
app.UseSwaggerUI();
//}
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.UseCors(opt =>
{
opt.WithOrigins("http://localhost:8080").AllowAnyHeader().AllowAnyMethod().AllowCredentials();
});
#region SignalR
app.MapHub<WarningBroadcastHub>("/sr/warning_broadcast");
#endregion
app.Run();
问题分析
- 通过观察客户端的错误信息发现是一个post请求出现了跨域问题,所以可以确定问题的本质不是signalR的跨域问题,而是webapi的跨域问题。
- 在配置跨域的时候需要注意,同一个域名下的不同端口也属于跨域,所以配置跨域源的时候要增加端口
- 因为SignalR在连接前的post请求都是包含验证信息的,所以要支持AllowCredentials()