ASP.NET SignalR 系列(八)之跨域推送
前面几章讲的都是同域下的推送和订阅。这种讲讲如何跨域
对于SignalR来说,默认是不允许跨域的,因为安全问题。虽如此,但同时提供了跨域方案。
两种跨域方式:
1:JSONP
2:CORS
JSONP的方式比Cors更不安全。下面分别讲讲怎么使用
一、JSONP方式
服务端设置:
Startup.cs文件
public partial class Startup { public void Configuration(IAppBuilder app) { //JSONP方式 app.MapSignalR(new HubConfiguration() {EnableJSONP = true}); } }
然后在全局文件中Global.cs注册,允许jsonp
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); //注册为允许跨域,JSONP模式需要 var config = new HubConfiguration(); config.EnableJSONP = true; } }
前端:在其他项目中新建一个html文件
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <link href="/Content/bootstrap.min.css" rel="stylesheet" /> <script src="/Scripts/jquery-1.10.2.min.js"></script> <script src="http://localhost:59831/Scripts/jquery.signalR-2.3.0.min.js"></script> <script src="http://localhost:59831/signalr/hub/hubs"></script> <!--指向集线器服务器--> <meta charset="utf-8" /> <style type="text/css"> body { margin: 20px; } .input { padding-left: 5px; } </style> </head> <body> <div> <h4>这是跨域的页面</h4> <hr /> <p> <input type="text" id="content" placeholder="发送内容" class="input" /> <input type="button" value="发送" class="btn btn-sm btn-info" id="btn_send" /> </p> <div> <h4>接收到的信息:</h4> <ul id="dataContainer"></ul> </div> </div> <script language="javascript"> $(function () { $.connection.hub.url = 'http://localhost:59831/signalr'; //指定signalR服务器,这个是关键,signalR为固定,系统默认。除非集线器那边重定义。 var chat = $.connection.demoHub; //连接服务端集线器,demoHub为服务端集线器名称,js上首字母须改为小写(系统默认) //定义客户端方法,此客户端方法必须与服务端集线器中的方法名称、参数均一致。 //实际上是服务端调用了前端的js方法(订阅) chat.client.show = function (content) { var html = '<li>' + htmlEncode(content) + "</li>"; $("#dataContainer").append(html); } //定义推送,跨域启动时,必须指定 jsonp:true $.connection.hub.start({ jsonp: true }) .done(function () { $("#btn_send").click(function () { chat.server.hello($("#content").val()); //将客户端的content内容发送到服务端 $("#content").val(""); }); }); }); //编码 function htmlEncode(value) { var encodedValue = $('<div />').text(value).html(); return encodedValue; } </script> </body> </html>
上效果图:
从上图可以看到,用到的域名不同,一个端口号59831 ,一个61625。实现了跨域
第二种:Cors 模式
该模式需要下载Microsoft.Owin.Cors组件,可从Nuget中获取
安装完成后,注册Strartup.cs文件
public void Configuration(IAppBuilder app) { ////系统默认 //app.MapSignalR(); //JSONP方式 //app.MapSignalR(new HubConfiguration() {EnableJSONP = true}); //Cors跨域模式 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); }); }
如果需要同时兼容 JSONP,那么将上面EnableJSONP = true 注释取消即可。
cors模式,不需要再global中注册了,如果要兼容JSONP,那么注册还是需要保留
下面上前端:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <link href="/Content/bootstrap.min.css" rel="stylesheet" /> <script src="/Scripts/jquery-1.10.2.min.js"></script> <script src="http://localhost:59831/Scripts/jquery.signalR-2.3.0.min.js"></script> <script src="http://localhost:59831/signalr/hub/hubs"></script> <meta charset="utf-8" /> <style type="text/css"> body { margin: 20px; } .input { padding-left: 5px; } </style> </head> <body> <div> <h4>这是跨域的页面</h4> <hr /> <p> <input type="text" id="content" placeholder="发送内容" class="input" /> <input type="button" value="发送" class="btn btn-sm btn-info" id="btn_send" /> </p> <div> <h4>接收到的信息:</h4> <ul id="dataContainer"></ul> </div> </div> <script language="javascript"> $(function () { $.connection.hub.url = 'http://localhost:59831/signalr'; //指定signalR服务器 jQuery.support.cors = true; //Cors模式必须设置 var chat = $.connection.demoHub; //连接服务端集线器,demoHub为服务端集线器名称,js上首字母须改为小写(系统默认) //定义客户端方法,此客户端方法必须与服务端集线器中的方法名称、参数均一致。 //实际上是服务端调用了前端的js方法(订阅) chat.client.show = function (content) { var html = '<li>' + htmlEncode(content) + "</li>"; $("#dataContainer").append(html); } //定义推送,启动时无需再设置jsonp:true $.connection.hub.start() .done(function () { $("#btn_send").click(function () { chat.server.hello($("#content").val()); //将客户端的content内容发送到服务端 $("#content").val(""); }); }); }); //编码 function htmlEncode(value) { var encodedValue = $('<div />').text(value).html(); return encodedValue; } </script> </body> </html>
效果如下图:
至此,两种跨域模式均讲解完成。
cors相对来说安全性比较高,但是对客户端要求比较高,比如低版本的IE不支持。
JSONP的模式安全性较低,但是对低版本IE兼容比较好。
所以再使用的时候,根据实际情况做选择,或者同时兼容。