前言
大概两年前公司有个项目需要用到服务端推送功能,由于用到了移动端,当时SignalR在移动端没有相应的SDK,于是乎放弃了这个方案,改用MQTT。这两年随着.net core的流行,SignalR也一直没有被微软放弃,并且做了很多的工作,于是动手写了个小Demo。在测试过程中由于前后台分离,涉及到了跨域问题,经过详细的搜查,发现网上很多人写的博客都不喜欢标注运行环境,这样就导致浪费了太多的时间。
环境
运行环境:.Net 5(自带SignalR功能)
开发环境:VS2019 16.8.2
客户端现象
根据描述应该就是跨域问题,基于浏览器同源策略(这是一种浏览器的安全保护措施),在浏览器,当发送javascript的脚本请求的时候,浏览器会检测这个javascript脚本是否是来自同一个来源,如果不是,浏览器会认为脚本是不安全的,不敢用。
同源策略:要求协议、域名、端口号、都要相同
客户端解决
也就是在html请求页面加上相应的判断来解决跨域问题,这个可以参考jsonp 方法,比较老的一种通用方法,这里不详述了。
服务端解决
也就是后端跨域的设置,个人觉得这是一种比较优雅的解决方法,通过在服务端的接口调用处加上相应的判断。
.Net Framework
通过截取前端发来的请求,加上允许跨域访问
Response.AddHeader("Access-Control-Allow-Origin", "*");
.Net core 3.1及之前
services.AddCors(options =>
{
options.AddPolicy("any", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
});
});
允许任何跨域的请求,也可以单独对某些ip进行设置
services.AddCors(options =>
{
options.AddPolicy("origin", builder =>
{
builder.WithOrigins("http://localhost:8080",
"http://192.168.1.222:8080/").AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
//builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials();
});
});
最后需要在Configure里加上:app.UseCors(“any”);
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("any");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<ChatHub>("/chathub");
});
}
.Net 5
在.net 5之后会发现按上面的设置直接报错了
所以这里要这样设置:
services.AddCors(options =>
{
options.AddPolicy("any", builder =>
{
builder.SetIsOriginAllowed(_=>true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
});
});
具体的原因可以参考微软官方的文档:
链接: https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-5.0.
同样最后也需要加上app.UseCors(“any”);
结语
再次请求各位写博客的大佬请一定注明开发环境及程序运行版本,不然你还不如不写。