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" />&nbsp;&nbsp;<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" />&nbsp;&nbsp;<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兼容比較好。
所以再使用的時候,根據實際情況做選擇,或者同時兼容。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM