正如我在以前的几篇文章中所描述的那样,自我托管SignalR很是容易设置。这很容易作到,若是您须要将SignalR做为事件源链接到标准的基于Windows的应用程序(如服务,甚至是须要向许多用户发送推送通知的WPF或Winforms桌面应用程序),这很好html

自托管的一个方面虽然不是那么透明或有记录,可是在SSL下运行自托管的SignalR服务。Windows证书存储以及证书的建立,配置和安装仍然很痛苦,由于Windows中没有提供连接端点到证书的UI,而且该流程的端到端记录不完整。一旦你知道须要调用什么命令行工具就很容易,可是这个过程固然能够更顺畅,更好地记录。所以,我在这里从新讨论这个主题,以提供更多详细信息,并但愿可以更加一致地描述为自我托管OWIN服务(特别是SignalR)设置证书。java

自托管和OWIN

当您本身托管SignalR时,您实际上使用的是OWIN / Katana提供的托管服务。OWIN是一个低级规范,用于实现可互换使用的自定义托管提供程序。咱们的想法是将托管进程与特定实现分离并使其可插拔,所以您能够选择托管实现。ios

Katana是Microsoft的OWIN实现,它提供了几个特定的​​实现。对于自托管,基于HttpListener的主机与IIS及其基础架构彻底分离。对于在ASP.NET内部托管,还有一个基于ASP.NET的实现,用于在ASP.NET内部运行的SignalR应用程序。这两种实现都为SignalR提供了基本托管支持,所以大多数状况下,相同的代码库可用于在ASP.NET下运行SignalR,或者在您本身的自托管EXE(如服务,控制台或桌面应用程序)下运行。web

将证书绑定到SSL端口以进行自托管

HttpListener下的自托管很是精彩且彻底独立,但不属于IIS的一个缺点是它也不知道为IIS安装的证书,这意味着您要使用的证书必须是显式绑定到端口。请注意,您可使用IIS证书,若是须要获取完整证书以用于自托管应用程序,则经过IIS证书过程是获取证书的最简单方法。若是你须要一个本地测试证书,IIS的自签名证书建立工具也很容易(我将在下面描述)。shell

如今让咱们假设您已经在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 

这给你一个这样的显示:

netsh的

查找CertHash

我在上面提到了certhash:要找到certhash,你须要找到证书的ThumbPrint,它能够经过如下几种方式找到:

  • IIS证书管理器
  • Windows证书存储管理器

使用IIS获取证书信息

若是安装了IIS,前者是最简单的。在这里,您能够轻松查看全部已安装的证书,此UI也是建立本地自签名证书的最简单方法。

要查找现有证书,只需打开IIS管理控制台,转到计算机节点,而后转到服务器证书:

IISCerts

您能够在最右侧的列中看到证书哈希。您也能够双击并打开证书,而后进入证书的详细信息。查找包含哈希的指纹。

CertificateDetails 

遗憾的是,这些位置都不容易复制哈希,所以您必须手动复制它或从对话框中的指纹数据中删除空格。

使用IIS建立自签名证书

若是您尚未完整的服务器证书,可是您但愿在本地使用SSL操做进行测试,则还可使用IIS Admin界面轻松建立自签名证书。IIS管理控制台提供了建立本地自签名证书的最简单方法之一。

这是怎么作的:

  • 转到IIS服务管理器的计算机根目录
  • 转到IIS部分中的服务器证书项
  • 在左侧单击“建立自签名证书”
  • 为其命名,而后选择我的存储
  • 单击肯定

IisCreateCert

这就是建立自签名本地证书的所有内容。

将自签名证书复制到受信任的根证书存储区

拥有自签名证书后,还须要一个步骤才能使证书受信任,所以Http客户端将在您的计算机上接受它而不会出现证书错误。该过程涉及将证书从我的存储复制到受信任的机器商店。

去作这个:

  • 从StartMenu使用“ 管理计算机证书”
  • 进入我的| 证书并找到您的证书
  • 将证书拖放并复制(Ctrl-拖动)为“受信任的根证书” 证书

TrustCertificate

您如今应该拥有浏览器可信赖的证书。这适用于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的任何自托管应用程序。

资源