22

在研究中尝试了我的运气,但到目前为止没有任何乐趣。

我想将 SignalR javascript 客户端连接到自托管 SignalR Windows 服务绑定到自签名 SSL 证书。

我的应用程序在 http 上运行良好,但是当 Owin WebApplication 开始使用 https 时,客户端反复断开连接。

这是我为使用 SSL 配置 SignalR 所做的工作。

  1. 使用 IIS 创建自签名证书
  2. 将证书导入 mmc 中的受信任的根证书颁发机构(不确定是否有帮助)
  3. 运行 NETSH 命令将 SSL 绑定到端口 8080

    netsh http add sslcert ipport=0.0.0.0:8080 certhash=123456f6790a35f4b017b55d09e28f7ebe001bd appid={12345678-db90-4b66-8b01-88f7af2e36bf}
    
  4. 在自托管的 HubConnection 实例中添加了代码以添加这样的导出 SSL(尽管这无关紧要,因为它是无法连接的客户端):

    if (File.Exists("MyCert.cer") 
        && Settings.GetSetting(Settings.Setting.SrProtocol).Equals("https", StringComparison.InvariantCultureIgnoreCase))
            connection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer"));
    
  5. 使用 https 启动 Owin WebApplication(这应该在 http.sys 中创建绑定)

    string registerUrl = string.Format("{0}://SOME.WHERE.COM:{1}", Service.Server.SrProtocol, Service.Server.SrPort);
    WebApp.Start<StartUp>(registerUrl);
    

在 SignalR 2.0 文档中,它说:

要启动 Web 服务器,请调用 WebApplication.Start(endpoint)。您现在应该能够在浏览器中导航到端点/信号器/集线器。

当我浏览到 URL http://SOME.WHERE.COM:8080/signalr/hubs时,我成功接收到驱动 SignalR 的 javascript。

当我浏览到 URL https://SOME.WHERE.COM:8080/signalr/hubs时,我没有成功,我使用 FF 收到“与服务器的连接已重置”。

我考虑过的一些附加点:

  • NETSH SHOW 表示 url 已注册

    URL group ID: E300000240000022
    State: Active
    Request queue name: Request queue is unnamed.
    Properties:
        Max bandwidth: inherited
        Max connections: inherited
        Timeouts:
            Timeout values inherited
        Number of registered URLs: 1
        Registered URLs: HTTPS://SOME.WHERE.COM:8080/
    
  • NETSH SHOW 表示 SSL 证书绑定到 8080:

    IP:port                 : 0.0.0.0:8080 
    Certificate Hash        : 123456f6790a35f4b017b55d09e28f7ebe001bd
    Application ID          : {12345678-db90-4b66-8b01-88f7af2e36bf} 
    Certificate Store Name  : (null) 
    Verify Client Certificate Revocation    : Enabled
    Verify Revocation Using Cached Client Certificate Only    : Disabled
    Usage Check    : Enabled
    Revocation Freshness Time : 0 
    URL Retrieval Timeout   : 0 
    Ctl Identifier          : (null) 
    Ctl Store Name          : (null) 
    DS Mapper Usage    : Disabled
    Negotiate Client Certificate    : Disabled
    

任何帮助是极大的赞赏!

4

1 回答 1

20

我相信它现在对我有用。这是我为使事情顺利进行所采取的步骤的简要说明:

SSL 说明

SSL & SignalR (Owin WebApplication) 需要将证书绑定到端口。

  1. 使用 IIS 生成自签名证书,这应该将证书放入 CERTMGR 的 LOCAL COMPUTER > Personal > Certificates 文件夹中
  2. 在 CERTMGR shift+drag 证书到 LOCAL COMPUTER > Trusted Root Certification Authorities > Certificates 文件夹,它应该在那里复制它
  3. 运行以下命令将 SSL 证书绑定到 0.0.0.0:8080

    netsh http add sslcert ipport=0.0.0.0:8080 certhash=123456f6790a35f4b017b55d09e28f7ebe001bd appid={12345678-db90-4b66-8b01-88f7af2e36bf} 
    netsh http show urlacl > D:\urlacl.txt
    

    输出:

    Reserved URL            : https://*:8080/ 
    User: SOMEWHERE\Administrator
    Listen: Yes
    Delegate: No
    SDDL: D:(A;;GX;;;S-1-5-21-138209071-46972887-2260295844-1106) 
    
  4. 运行以下 NETSH 命令将端口 8080 的所有 IP 地址保留到 My Service 应用程序 ID 和服务帐户

    netsh http add urlacl url=https://*:8080/ user=SOMEWHERE\Administrator listen=yes
    netsh http show sslcert > D:\sslcert.txt
    

    输出:

    IP:port                 : 0.0.0.0:8080 
    Certificate Hash        : 123456f6790a35f4b017b55d09e28f7ebe001bd
    Application ID          : {12345678-db90-4b66-8b01-88f7af2e36bf} 
    Certificate Store Name  : (null) 
    Verify Client Certificate Revocation    : Enabled
    Verify Revocation Using Cached Client Certificate Only    : Disabled
    Usage Check    : Enabled
    Revocation Freshness Time : 0 
    URL Retrieval Timeout   : 0 
    Ctl Identifier          : (null) 
    Ctl Store Name          : (null) 
    DS Mapper Usage    : Disabled
    Negotiate Client Certificate    : Disabled
    
  5. 更新 MyServices.exe.config 文件以使用 https 协议(这些是 appSetting 键,用于在 My Service 启动时动态设置 SignalR 的协议和端口)

    <add key="SrProtocol" value="https" />
    <add key="SrPort" value="8080" />
    
  6. 使用 NETSTAT START 命令启动我的服务

  7. 运行以下 NETSH 命令,显示服务状态正在占用注册的 url

    netsh http show servicestate > D:\servicestate.txt
    

    输出:

    Server session ID: C300000320000039
    Version: 2.0
    State: Active
    Properties:
        Max bandwidth: 4294967295
        Timeouts:
            Entity body timeout (secs): 120
            Drain entity body timeout (secs): 120
            Request queue timeout (secs): 120
            Idle connection timeout (secs): 120
            Header wait timeout (secs): 120
            Minimum send rate (bytes/sec): 150
    URL groups:
    URL group ID: C600000340000138
        State: Active
        Request queue name: Request queue is unnamed.
        Properties:
            Max bandwidth: inherited
            Max connections: inherited
            Timeouts:
                Timeout values inherited
            Number of registered URLs: 1
            Registered URLs:
                HTTPS://*:8080/
    

我的应用程序不依赖于 IIS,但是一旦我使用 IIS 临时创建一个绑定到我的 SSL 证书的端口,我的应用程序就开始工作,并且我能够检查 NETSH 服务状态以了解 IIS 是如何做到的。我已经放弃了 IIS 绑定并运行了设置说明,并且仍然成功。

我的 Owing 启动看起来像这样:

private void configureMessaging()
{
    string registerUrl = string.Format("{0}://*:{1}", Service.Server.SrProtocol, Service.Server.SrPort);

    try
    {
#if DEBUG
        //System.Diagnostics.Debugger.Launch();
#endif
        //  Starts an owin web application to host SignalR, using the protocol and port defined.
        WebApp.Start<StartUp>(registerUrl);
    }
    catch (Exception ex)
    {
        Logger.Logs.Log(string.Format("Failed to configure messaging.  Exception: {0}", ex.RecurseInnerException()), LogType.Error);            

        if (ex is HttpListenerException || ex.InnerException is HttpListenerException)
        {
            try
            {
                Process p = new Process();
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.FileName = "netsh.exe";
                p.StartInfo.Arguments = string.Format("netsh http delete urlacl url={0}"
                    , registerUrl
                    );
                p.Start();
                p.StandardOutput.ReadToEnd();
                p.WaitForExit();
            }
            catch (Exception exP)
            {
                Logger.Logs.Log(string.Format("Failed to delete urlacl {0}.  Exception: {1}"
                    , registerUrl
                    , exP.RecurseInnerException()
                    )
                    , LogType.Error
                    )
                    ;

                retries = 5;
            }
        }

    if (retries < 5)
    {
        retries++;

        Logger.Logs.Log(string.Format("Attempting to configure messaging again.  Attempt No. {0}", retries), LogType.Warn);

        Thread.Sleep(1000);

        configureMessaging();
    }
    else
        Logger.Logs.Log(string.Format("Exceeded total number of retries to configure messaging.", retries), LogType.Error);

    }

}

自托管的 HubConnetion 实例如下所示:

    public IHubProxy MyHubProxy
    {
        get
        {
            if (this._MyHubProxy == null)
            {
                var connection = new HubConnection(string.Format("{0}://{1}:{2}/"
                    , Settings.GetSetting(Settings.Setting.SrProtocol)
                    , MyHub.GetLocalhostFqdn(null)
                    , Settings.GetSetting(Settings.Setting.SrPort)
                    )
                    )
                    ;
                this._MyHubProxy = connection.CreateHubProxy("MyHub");

                if (File.Exists("My.cer")
                    && Settings.GetSetting(Settings.Setting.SrProtocol).Equals("https", StringComparison.InvariantCultureIgnoreCase))
                    connection.AddClientCertificate(X509Certificate.CreateFromCertFile("My.cer"));

                connection.Start().Wait();
            }

            return this._MyHubProxy;
        }
    }

这里的代码比相关代码多一点,但希望它可能会有所帮助!

于 2013-08-10T18:16:38.473 回答