SignalR 和跨域问题 (ASP.NET)

SignalR 有三块,

Server:
  Hub Server
  Custom Message Sender Service (Sender Proxy)

Client:
  Message Sender
  Message Receiver

1. Hub Server & Sender Proxy Service
Hub Server 和 Custom Message Sender Service 在一个app中,“Custom Message Sender Service” 通过api直接控制Hub Server行为。(connection filtering, status, deliver message, etc )

2. 跨域
Sender, Receiver 和 Hub Server 可能都不在同一个域里。 会有跨域访问的问题。

3. 发消息的客户端
可以有两种方式发消息给Hub Server
  3.1 通过hubproxy.server.func(), 走的是signalR的persistent connection. (这种情形下一般只发一次消息,persistent connection占用了资源,浪费。 当然也可以建立完释放,persistent connection -> send message -> close persistent connection)。 这种模式下,跨域由SignalR Hub框架控制。
  3.2 通过ajax调用 "Custom Message Sender Service (Proxy)", 由Proxy调用Hub的服务。 这种结构更干净,发送者和SignalR connection没有关系, 走单独Http请求。 跨域由 "Custom Message Sender Service (Proxy)", 一般由服务端暴露服务(MVC/WebAPI). 但是MVC和WebApi的跨域管理不太一样。(见“MVC和WebApi的跨域管理”)
  3.3 有一种情况可以考虑用signalR的persistent connection发消息。 就是发消息的人,同时又是收消息的人。 那么一个persistent connection可以同时用来收发消息。

4. 收消息的客户端
这个只有一种,“持久连接,保持监听”。
  4.1 SignalR保持连接的方式由协议本身定义,由服务器和浏览器支持。 WebSocket / iFrame / longPooling。 具体可google
  4.2 WebSocket的效率要比其他高很多,比较reliable,比如disconnect, 其他方式可能不能直接反应客户端关闭的动作,需要等待超时发生触发disconnect. 代码和排错上有时比较费解。
  4.3 【Hub Server服务端】微软的WebApp PaaS上, by default, "WebSocket"不enable。要去管理界面把它打开。

5. Hub Server
  5.1 Owin中map /signalr 作为SignalR routing的开始
     (https://docs.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server#tracing If you are adding SignalR functionality to an ASP.NET MVC application, make sure that the SignalR route is added before the other routes. For more information, see Tutorial: Getting Started with SignalR 2 and MVC 5.)
  5.2 跨域访问由Owin框架自己处理, 如果再由IIS web.config来控制CORS, 会产生冲突。
  5.3 Hub Server中的方法,只是个签名,具体实现不重要(无需写实现,除非客户端用hub.server.func()发消息)。 主要作用
    5.3.1 生成客户端代理类。
    5.3.2 让代理类绑定本地方法,以被服务端调用

 6. Sender Message Proxy
  6.1 如果用MVC做,有个很大的问题就是,跨域。 
    6.1.1 如果浏览器是IE, 问题不是很大。 貌似preflight request 被省略了。 request 被直接提交到MVC层, 可以自定义Action属性, 加入”Access-Control-Allow-Origin“。
    6.1.2 如果浏览器是Chrome, "preflight request"不会被忽略. http option verb会发过来。 这个时候MVC就有问题了, 无论从owin还是application_beginRequest,都无法获得这个request,无法修改http头,使得CORS通过。 (猜想是不是MVC的routing,所在的层次太高,获得不了这种request)
    6.1.3 对于simple CORS, IE 和 Chrome (Chrome 无须preflight), 如果用Get/Post传数据,由于不走preflight, 自定义Action属性修改http header是可行的。 但是如果用ajax, 有content type header的话, 那就必须要走preflight.

7. IIS setting, web.config 
  实际使用当中,如果使用MVC 和 SignalR, 客户端用ajax post json (content type = application / json), 那么需要考虑直接使用直接从服务器设置应用CORS。 这个时候SignalR的CORS需要被取消(//map.UseCors(CorsOptions.AllowAll) )

    <add name="Access-Control-Allow-Origin" value="https://localhost:44300" />
    <add name="Access-Control-Allow-Headers" value="Content-Type" />
    <add name="Access-Control-Allow-Credentials" value="true" />

CORS 介绍

  一篇很好的文章介绍CORS:https://staticapps.org/articles/cross-domain-requests-with-cors/

  注意Simple CORS / Complex CORS 的区别

常用代码

var heartBeat = GlobalHost.DependencyResolver.Resolve<ITransportHeartbeat>();
var connectionAlive = heartBeat.GetConnections().FirstOrDefault(c=>c.ConnectionId == connection.ConnectionId);
if (connectionAlive.IsAlive)
{//Do whatever...}

======================================================

IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
IHubContext context = GlobalHost.ConnectionManager.GetHubContext(“MyHub”);

======================================================

public class EnableCorsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);
    }
}

时间: 2024-08-30 05:12:09

SignalR 和跨域问题 (ASP.NET)的相关文章

http与websocket两种协议下的跨域基于ASP.NET MVC--竹子整理

这段时间,项目涉及到移动端,这就不可避免的涉及到了跨域的问题.这是本人第一次接触跨域,有些地方的配置是有点麻烦,导致一开始的不顺. 至于websocket具体是什么意义,用途如何:请百度. 简单说就是建立一个基于互联网的实时通信. 在这里整理下这些内容,方便日后回顾. 一:介绍了WebSocket下的基于SignalR的跨域与不跨域例子 二:简单介绍了Http下的跨域问题 Ⅰ.WebSocket下的跨域 如果使用原生的方法来开发WebSocket应用,还是比较复杂的,不过好在Asp.net给我们

浅谈Web Api配合SignalR的跨域支持

最近接手的一个项目中,涉及到一个简单的消息模块,由于之前有简单了解过SignalR,所以打算尝试着摸索摸索~! 首先,通过Nuget管理器添加Microsoft ASP.NET SignalR引用~目前最新版本2.2.0,依赖项目也有点多,什么Microsoft.AspNet.SignalR.JS,Microsoft.AspNet.SignalR.SystemWeb,还有Owin相关的项目,没法咯,一起统一引用! 添加启动设置 1 [assembly: OwinStartup(typeof(Si

ASP.NET Core SignalR CORS 跨域问题

将 SignalR 集成到 ASP.NET Core api 程序的时候,按照官方 DEMO 配置完成,本地访问没有问题,但是发布之后一直报跨域问题,本地是这样设置的: 原始代码: services.AddCors(op => { op.AddPolicy("cors", set => { set.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); 原因: 出现该

关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案

原文:http://www.cnblogs.com/chenxizhang/p/3821703.html 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 1.使用模板创建一个最简单的ASP.NET Web API项目,调试起来确认能正常工作 public class TestController : ApiController { // GET api/test public IEnumera

支持Ajax跨域访问ASP.NET Web Api 2(Cors)的简单示例教程演示

随着深入使用ASP.NET Web Api,我们可能会在项目中考虑将前端的业务分得更细.比如前端项目使用Angularjs的框架来做UI,而数据则由另一个Web Api 的网站项目来支撑.注意,这里是两个Web网站项目了,前端项目主要负责界面的呈现和一些前端的相应业务逻辑处理,而Web Api则负责提供数据. 这样问题就来了,如果前端通过ajax访问Web Api项目话,就涉及到跨域了.我们知道,如果直接访问,正常情况下Web Api是不允许这样做的,这涉及到安全问题.所以,今天我们这篇文章的主

AJAX跨域调用ASP.NET MVC或者WebAPI服务的解决方案

问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模板创建一个最简单的ASP.NET Web API项目,调试起来确认能正常工作 public class UserController : ApiController { public UserModel getInfo() { UserModel um = new UserModel(); um.Uid = 5; um.UserName =

如何通过js跨域调用ASP.NET Web API (请问如何实现在javascript中通过http get的方式跨域调用ASP.NET Web API?)

客户端js无需任何专门设置,使用通常的ajax调用即可: $.ajax({ url: '跨域URL', type: 'get', dataType: 'json', success: function (data) { $('#banner_right').html(data); } }); 服务端需要在WebApiConfig.Register()中添加如下的代码 public static class WebApiConfig { public static void Register(Ht

Asp.Net 跨域,Asp.Net MVC 跨域,Session共享

比如 http://www.test.com 和 http://m.test.com 简单粗暴的方法 Web.Config <system.web> <!--其他配置 省略……--> <httpCookies domain="test.com" /><!--同一顶级域名--> </system.web> <handlers> <!--其他配置 省略……--> <!--<remove name

SignalR 的跨域支持

How to establish a cross-domain connection Typically if the browser loads a page from http://contoso.com, the SignalR connection is in the same domain, athttp://contoso.com/signalr. If the page from http://contoso.com makes a connection to http://fab