https://weblog.west-wind.com/posts/2013/Sep/23/Hosting-SignalR-under-SSLhttps
正如我在之前的幾篇文章中所描述的那樣,自我托管SignalR非常容易設置。這很容易做到,如果您需要將SignalR作為事件源連接到標准的基於Windows的應用程序(如服務,甚至是需要向許多用戶發送推送通知的WPF或Winforms桌面應用程序),這很好。
自托管的一個方面雖然不是那么透明或有記錄,但是在SSL下運行自托管的SignalR服務。Windows證書存儲以及證書的創建,配置和安裝仍然很痛苦,因為Windows中沒有提供鏈接端點到證書的UI,並且該流程的端到端記錄不完整。一旦你知道需要調用什么命令行工具就很容易,但是這個過程當然可以更順暢,更好地記錄。因此,我在這里重新討論這個主題,以提供更多詳細信息,並希望能夠更加一致地描述為自我托管OWIN服務(特別是SignalR)設置證書。
自托管和OWIN
當您自己托管SignalR時,您實際上使用的是OWIN / Katana提供的托管服務。OWIN是一個低級規范,用於實現可互換使用的自定義托管提供程序。我們的想法是將托管進程與特定實現分離並使其可插拔,因此您可以選擇托管實現。
Katana是Microsoft的OWIN實現,它提供了幾個特定的實現。對於自托管,基於HttpListener的主機與IIS及其基礎架構完全分離。對於在ASP.NET內部托管,還有一個基於ASP.NET的實現,用於在ASP.NET內部運行的SignalR應用程序。這兩種實現都為SignalR提供了基本托管支持,因此大多數情況下,相同的代碼庫可用於在ASP.NET下運行SignalR,或者在您自己的自托管EXE(如服務,控制台或桌面應用程序)下運行。
將證書綁定到SSL端口以進行自托管
HttpListener下的自托管非常精彩且完全獨立,但不屬於IIS的一個缺點是它也不知道為IIS安裝的證書,這意味着您要使用的證書必須是顯式綁定到端口。請注意,您可以使用IIS證書,如果需要獲取完整證書以用於自托管應用程序,則通過IIS證書過程是獲取證書的最簡單方法。如果你需要一個本地測試證書,IIS的自簽名證書創建工具也很容易(我將在下面描述)。
現在讓我們假設您已經在Windows證書庫中安裝了證書。為了將證書綁定到自托管端點,您必須使用netsh命令行實用程序在計算機上注冊它(全部在一行上):
netsh http add sslcert ipport=0.0.0.0:8082 appid={12345678-db90-4b66-8b01-88f7af2e36bf} certhash=d37b844594e5c23702ef4e6bd17719a079b9bdf
對於每個端點映射,您需要提供3個值:
-
標識ip和端口的
ipport指定為ipport = 0.0.0.0:8082,其中零表示端口8082上的所有IP地址。否則,您還可以指定特定的IP地址。 -
certhash是證書的指紋
certhash是將證書映射到上面的IP端點的id。您可以通過查看Windows證書存儲區中的證書來查找此哈希。更多關於這一點。 -
為HttpListener Hosting修復的AppID
此值是靜態魔術值,因此始終使用appid={12345678-db90-4b66-8b01-88f7af2e36bf}。一旦運行了上述命令,您應該通過查看綁定來檢查它是否有效。用這個:
netsh http show sslcert ipport=0.0.0.0:8082
這給你一個這樣的顯示:
查找CertHash
我在上面提到了certhash:要找到certhash,你需要找到證書的ThumbPrint,它可以通過以下幾種方式找到:
- IIS證書管理器
- Windows證書存儲管理器
使用IIS獲取證書信息
如果安裝了IIS,前者是最簡單的。在這里,您可以輕松查看所有已安裝的證書,此UI也是創建本地自簽名證書的最簡單方法。
要查找現有證書,只需打開IIS管理控制台,轉到計算機節點,然后轉到服務器證書:
您可以在最右側的列中看到證書哈希。您也可以雙擊並打開證書,然后進入證書的詳細信息。查找包含哈希的指紋。
遺憾的是,這些位置都不容易復制哈希,因此您必須手動復制它或從對話框中的指紋數據中刪除空格。
使用IIS創建自簽名證書
如果您還沒有完整的服務器證書,但是您希望在本地使用SSL操作進行測試,則還可以使用IIS Admin界面輕松創建自簽名證書。IIS管理控制台提供了創建本地自簽名證書的最簡單方法之一。
這是怎么做的:
- 轉到IIS服務管理器的計算機根目錄
- 轉到IIS部分中的服務器證書項
- 在左側單擊“創建自簽名證書”
- 為其命名,然后選擇個人存儲
- 單擊確定
這就是創建自簽名本地證書的全部內容。
將自簽名證書復制到受信任的根證書存儲區
擁有自簽名證書后,還需要一個步驟才能使證書受信任,因此Http客戶端將在您的計算機上接受它而不會出現證書錯誤。該過程涉及將證書從個人存儲復制到受信任的機器商店。
去做這個:
- 從StartMenu使用“ 管理計算機證書”
- 進入個人| 證書並找到您的證書
- 將證書拖放並復制(Ctrl-拖動)為“受信任的根證書” 證書
您現在應該擁有瀏覽器可信賴的證書。這適用於IE,Chrome和Safari,但FireFox需要一些特殊步驟(感謝Eric Lawrence),Opera還需要特定的證書注冊。
使用完整的IIS證書
自簽名證書非常適合在SSL下進行測試以確保您的應用程序正常工作,但對於生產應用程序而言並不是很好,因為證書必須安裝在您希望信任此證書的任何計算機上,這是一件麻煩事。
一旦你去生產,特別是公共生產,你需要一個由$$$的全球證書頒發機構簽署的“官方”證書(或者現在是LetsEncrypt)。
最簡單的方法是購買或生成完整的IIS證書並將其安裝在IIS中。IIS證書也可以用於使用HttpListener的自托管應用程序,因此它可以與自托管SignalR或任何HttpListener應用程序一起使用。
因此,一旦時間到了,請通過IIS注冊新證書,然后使用netsh http add sslcert如上所示注冊該證書。在大多數情況下,公共SSL證書已經被識別,因此不需要進一步移動證書存儲 - 您只需要將netsh注冊綁定到特定端口和應用程序ID。
使用SSL運行SignalR
安裝證書后,將SignalR切換為SSL啟動就像更改啟動URL一樣簡單。
自托管服務器配置
在自托管服務器中,您現在可以在啟動工廠調用中指定新的SSL URL:
var signalR = WebApp.Start<SignalRStartup>([https://*:8082/](https://*:8082/));
這會將SignalR綁定到端口8082上的所有IP地址。您還可以指定特定的IP地址,但使用*更具可移植性,尤其是將值設置為共享配置文件的一部分時。
如果你回憶起我上次的自托管帖子,OWIN使用一個啟動類(在這種情況下是SignalRStartup)來處理OWIN和SignalR HubConfiguration,但唯一需要改變的是啟動URL,你的自托管服務器已准備就緒走。
SignalR Web App頁面URL配置
在Web頁面上使用SignalR服務到集線器或連接更改腳本URL,為您的集線器或連接加載SignalR客戶端庫,如下所示:
<script src="[https://RasXps:8082/signalr/hubs">script>
這里的RasXps是我注冊證書的確切本地機器名。與所有證書一樣,請確保域名與證書的名稱完全匹配。對於本地計算機,如果證書已默認分配給本地計算機NetBios名稱,則表示不使用localhost。不要使用您的IP地址 - 使用分配證書的任何內容。
您還需要將集線器Url分配給您的SSL URL,作為調用$ connection.hub.start的SignalR啟動例程的一部分:
$.connection.hub.url = self.hubUrl; // ie. "[https://rasxps:8082/signalR](https://rasxps:8082/signalR);"
有關更多上下文,這是我用來啟動集線器的典型集線器啟動/錯誤處理程序設置例程:
startHub: function () { $.connection.hub.url = self.hubUrl; // ie. "https://rasxps:8082/signalR"; // capture the hub for easier access var hub = $.connection.queueMonitorServiceHub; // This means the <script> proxy failed - have to reload if (hub == null) { self.viewModel.connectionStatus("Offline"); toastr.error("Couldn't connect to server. Please refresh the page."); return; } // Connection Events hub.connection.error(function (error) { if (error) toastr.error("An error occurred: " + error.message); self.hub = null; }); hub.connection.disconnected(function (error) { self.viewModel.connectionStatus("Connection lost"); toastr.error("Connection lost. " + error); // IMPORTANT: continuously try re-starting connection setTimeout(function () { $.connection.hub.start(); }, 2000); }); // map client callbacks hub.client.writeMessage = self.writeMessage; hub.client.writeQueueMessage = self.writeQueueMessage; hub.client.statusMessage = self.statusMessage; … // start the hub and handle after start actions $.connection.hub .start() .done(function () { hub.connection.stateChanged(function (change) { if (change.newState === $.signalR.connectionState.reconnecting) self.viewModel.connectionStatus("Connection lost"); else if (change.newState === $.signalR.connectionState.connected) { self.viewModel.connectionStatus("Online"); // IMPORTANT: On reconnection you have to reset the hub self.hub = $.connection.queueMonitorServiceHub; } else if (change.newState === $.signalR.connectionState.disconnected) self.viewModel.connectionStatus("Disconnected"); }) .error(function (error) { if (!error) error = "Disconnected"; toastr.error(error.message); }) .disconnected(function (msg) { toastr.warning("Disconnected: " + msg); }); self.viewModel.connectionStatus("Online"); // get initial status from the server (RPC style method) self.getServiceStatus(); self.getInitialMessages(); }); },
從代碼角度來看,除了兩個小的URL代碼更改之外,SSL操作沒有任何變化,這很好。
而且......你已經完成了!
SSL配置
隨着越來越多的應用程序需要傳輸安全性,SSL使用變得越來越重要。即使您的自托管SignalR應用程序沒有明確要求SSL,如果SignalR客戶端托管在運行SSL的網頁內,您必須在SSL下運行SignalR,如果您希望它在沒有瀏覽器錯誤消息或故障的情況下運行一些瀏覽器會拒絕SSL頁面上的混合內容。
SSL配置總是拖累,因為它不直觀,需要一些研究。如果HttpListener證書配置就像今天或更好的IIS配置一樣簡單,如果自托管應用程序可以使用已安裝的IIS證書,那就太好了。不幸的是,它並不那么容易,你需要運行一個命令行實用程序,其中包含一些魔術ID。
安裝證書並不是火箭科學,但它並沒有完全記錄在案。在尋找信息的過程中,我發現了一些不相關的文章,討論了這個過程,但有些文章已經過時,其他文章沒有具體涉及SignalR甚至是自托管網站。所以我希望這篇文章能夠在適當的環境中更容易地找到這些信息。
本文重點介紹使用SSL的SignalR自托管,但相同的概念可以應用於使用HttpListener的任何自托管應用程序。





