前面幾章講的都是同域下的推送和訂閱。這種講講如何跨域
對於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兼容比較好。
所以再使用的時候,根據實際情況做選擇,或者同時兼容。