SignalR的跨網域支援

SignalR JS Client Hubs文件Cross Domain Support一節看到SignalR可利用JSONP實現跨網域呼叫。簡單的說,就是將SignalR Hub架在A網站,卻從B網站的網頁執行$.connection.hub.start()連上A網站的SignalR接收資料或傳送指令。乍看稀鬆平常,但網站寫多一點的老鳥都知道這個副本裡有個XHR跨網站存取的小王要解決,所幸SignalR已內建跨網域支援,所以我們就來寫幾行程式玩看看。

以下是一個獨立網頁,目前在扮演先前利用SignalR實現遠端程式遙控功能文章裡SignalRClient.exe的角色:

<!DOCTYPE html>
 
<html>
<head>
    <meta charset="utf-8" />
    <title>SignalR Cross-Site Web Page Client</title>
    <base href="http://localhost:19636" />
    <script src="/Scripts/jquery-1.6.4.js" type="text/javascript"></script>
    <script src="/Scripts/jquery.signalR-0.5.2.js" ></script>
    <script src="/SignalR/hubs" ></script>
    <script>
    $(function () {
        //與SignalR Hub建立連線
        var commHub = $.connection.commHub;
        //實做ShowMessage(msg)
        commHub.ShowMessage = function(msg) {
            $("body").append("<div>" + msg + "</div>");
        };
        //跨網域引用SignalR時,要設定hub.url, 並hub.start({ jsonp: true });
        $.connection.hub.url = "http://127.0.0.1:19636/signalr";
        $.connection.hub.start({ jsonp: true })
        .done(function() {
            commHub.register("XSS");
         });
    });
    </script>
</head>
<body>
</body>
</html>

將以上網頁SignalRClient.htm存在本機隨意資料夾下(或放到其他網站也行,只要不在CommHub所在的ASP.NET MVC網站上就會產生跨網域障礙),使用IE等瀏覽器開啟該網頁進行測試,則可在主控網頁看到其所註冊的名稱--XSS,也能傳送訊息顯示在該網頁上,實現了與SignalRClient.exe相似的功能。檢視該網頁的HTML原始碼,可發現SignalR JS Client是以<script>方式建立連線[見圖標(1)],其src為httq://127.0.0.1:19636/signalr/connect?transport=longPolling&connectionId=81b9...略...62b98&connectionData=%5B%7B%22name%22%3A%22CommHub%22%7D%5D&tid=4&callback=jQuery16407549852419734552_1341978125354&_=1341978125642,看到callback=jQuery164075…參數,判斷是透過jQuery.ajax()的jsonp dataType進行跨網域呼叫,而由[圖標(2)]的回傳結果也可驗證此點。最後,主控端送來的文字就順利呈現在網頁上囉! (見圖標(3),測試時我按了兩次Send,故文字出現兩次) 驗證了SignalR JavaScript Client的跨網域支援能力。

【後記】

測試過程發現IE9即使不啟甪{ jsonp: true }也能跨網域運作,但在Chrome上卻不然。追進原始碼,發現SignalR支援webSocket及longPolling兩種傳輸模式,而start()中有一小段邏輯,當發現URL跨網域而瀏覽器的XHR不支援Cross-Original Request Sharing時(簡稱CORS, SignalR透過$.support.cors偵測,IE9被判定不支援),會自動切換為jsonp=true,改用longPolling + JSONP克服障礙;而在不啟用JSONP的前題下,要做到跨網域XHR,則需要從Server端額外加入一些Access-Control-* Header[參考]。

由此可解釋未指定{ json: true }時,IE9因被強制切成jsonp=true而成功,Chrome未被切成jsonp模式,又因SignalR端又未加入CORS需要Header,故無法順利運作。

歡迎推文分享:
Published 11 July 2012 09:33 PM 由 Jeffrey
Filed under:
Views: 11,586



意見

# didkwaab said on 20 October, 2015 02:28 AM

  公交车上,忽然感到屁股上被谁摸了一下,回头一看,两个漂亮小姑娘。

  其中一个见回头,冲我甜甜一笑,我也报以微笑,心里美滋滋的。

  只听另一姑娘说:“妹妹,你能不能改掉随处擦鼻屎的坏习惯。

=== 文章不错,已经收藏 ===

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<July 2012>
SunMonTueWedThuFriSat
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication