.net 支持 HTTPS 的 Httplistener
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11403333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Httplistener with HTTPS support
提问by Walter Kelt
There seems to be a lot of confusing, sometimes conflicting, information with regards to making a .NET HTTPListener HTTPS capable. My understanding is as follows:
关于使 .NET HTTPListener 具有 HTTPS 能力,似乎有很多令人困惑,有时甚至相互冲突的信息。我的理解如下:
One's C# code needs an
httpsprefix (for example,https://*:8443) in order for the listener to understand that it needs to service SSL requests at this port.The actual SSL handshake happens under the covers and is handled by
http.sys(buried somewhere on the Windows machine). The C# code doesn't have to explicitly manage the SSL handshake, because it happens under the covers.One needs to have a "X.509 trusted certificate" on the
httpListenermachine, and somehow that certificate needs to be bound to port 8443 (in this example).
一个 C# 代码需要一个
https前缀(例如,https://*:8443),以便侦听器了解它需要在此端口为 SSL 请求提供服务。实际的 SSL 握手发生在幕后,由
http.sys(埋在 Windows 机器上的某处)处理。C# 代码不必显式管理 SSL 握手,因为它发生在幕后。需要在
httpListener机器上拥有“X.509 可信证书” ,并且该证书需要以某种方式绑定到端口 8443(在本例中)。
Is my understanding above correct? If not, please educate me.
我上面的理解正确吗?如果没有,请教育我。
Regarding X.509 certificates, my understanding is:
关于X.509证书,我的理解是:
- Use
makecertto create an X.509 certificate. This certificate gets stored in the personal store and needs to get moved over to the Trusted Store (this is where the HTTP listener will look). It seems I can usecertMgrto perform the move, or I can usemmcto effect the move. It seems there is more than one X.509 certificate format (DER,Base64,pks, pswd protected,pksprivate, etc.)... Is there a preferred format I should use?
- 使用
makecert创建的X.509证书。此证书存储在个人存储中,需要移至受信任存储(这是 HTTP 侦听器将查看的位置)。看来我可以certMgr用来执行移动,或者我可以mmc用来实现移动。似乎有不止一种 X.509 证书格式(DER、Base64、pks、 pswd 受保护、pks私有等)......是否有我应该使用的首选格式?
Once I get the certificate into the trusted store, I need to bind it to the TCP port. I am on Windows 7: should I be using httpcfgor netsh?
将证书放入受信任的存储区后,我需要将其绑定到 TCP 端口。我在 Windows 7 上:我应该使用httpcfg还是netsh?
回答by Walter Kelt
I did a bunch of homework and got this working. The steps to add SSL support for an .NET HttpListener are:
我做了一堆功课并得到了这个工作。为 .NET HttpListener 添加 SSL 支持的步骤是:
Update C# application code to include the
httpsprefix. Example:String[] prefixes = { "http://*:8089/","https://*:8443/" };That's it from the code aspect.
For the certificate side of things, using the Windows SDKcommand console or Visual Studio Professional command console
Use
makecert.exeto create a certificate authority. Example:makecert -n "CN=vMargeCA" -r -sv vMargeCA.pvk vMargeCA.cerUse
makecert.exeto create an SSL certificatemakecert -sk vMargeSignedByCA -iv vMargeCA.pvk -n "CN=vMargeSignedByCA" -ic vMargeCA.cer vMargeSignedByCA.cer -sr localmachine -ss MyUse MMC GUI to install CA in Trusted Authority store
- Use MMC GUI to install an SSL certificate in Personal store
Bind certificate to
IP address:portand application. Example:netsh http add sslcert ipport=0.0.0.0:8443 certhash=585947f104b5bce53239f02d1c6fed06832f47dc appid={df8c8073-5a4b-4810-b469-5975a9c95230}The certhash is the thumbprint from your SSL certificate. You can find this using mmc. The appid is found in Visual Studio...usually in assembly.cs, look for the GUID value.
更新 C# 应用程序代码以包含
https前缀。例子:String[] prefixes = { "http://*:8089/","https://*:8443/" };从代码方面来说就是这样。
对于证书方面的事情,使用Windows SDK命令控制台或 Visual Studio Professional 命令控制台
使用
makecert.exe创建的证书颁发机构。例子:makecert -n "CN=vMargeCA" -r -sv vMargeCA.pvk vMargeCA.cer使用
makecert.exe来创建一个SSL证书makecert -sk vMargeSignedByCA -iv vMargeCA.pvk -n "CN=vMargeSignedByCA" -ic vMargeCA.cer vMargeSignedByCA.cer -sr localmachine -ss My使用 MMC GUI 在 Trusted Authority 存储中安装 CA
- 使用 MMC GUI 在个人存储中安装 SSL 证书
将证书绑定到
IP address:port应用程序。例子:netsh http add sslcert ipport=0.0.0.0:8443 certhash=585947f104b5bce53239f02d1c6fed06832f47dc appid={df8c8073-5a4b-4810-b469-5975a9c95230}certhash 是来自您的 SSL 证书的指纹。您可以使用 mmc 找到它。appid 可在 Visual Studio 中找到...通常在 assembly.cs 中,查找 GUID 值。
There may be other ways to accomplish the above, but this worked for me.
可能还有其他方法可以完成上述操作,但这对我有用。
回答by jpaugh
Here are the steps, in detail, that I followed to set up a stand-alone server on Windows, using OpenSSL to create the self-signed certificate for a C# HTTPListenerapplication. It includes plenty of links, in case you want to do further research.
以下是我在 Windows 上设置独立服务器的详细步骤,使用 OpenSSL 为 C#HTTPListener应用程序创建自签名证书。它包含大量链接,以防您想进一步研究。
Create a stand-alone server in .NET via
HttpListener:var prefixes = {"http://localhost:8080/app/root", "https://localhost:8443/app/root"}; var listener = new HttpListener(); foreach (string s in prefixes) listener.Prefixes.Add(s); listener.Start();Create self-signed certificate:*
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365, which will prompt you for the value of each of the certificate's fields on the command line. For the common name, type the domain name (e.g.localhost)openssl pkcs12 -inkey bob_key.pem -in bob_cert.cert -export -out bob_pfx.pfx, so that it can be imported with its key on the target machine.
*For an alternative using
makecert, see Walter's own answer.Open Certificate Manager for the Local Machine. When you run
certmgr.msc, it opens the Certificate Manager for the current user, which is not what we want here. Instead:- From an administrative command prompt on the target machine, run
mmc - Press Ctrl+ M, or Click File> Add/Remove Snap-in
- Choose
Certificates, and click Add > - In the dialog that appears, Choose
Computer Account, and click Next - Choose
Local Computer. Click Finish, then Okay
- From an administrative command prompt on the target machine, run
Import the certificate (
pfx) into the Windows Certificate Storeon the target machine- In the
mmcwindow previously opened, drill down to Certificates (Local Computer)> Personal - Right-click on
Personal, then click on All Tasks-> Import... - In the 2nd screen of the dialog that appears, find and import your certificate. You'll have to change the file-type filter to
Personal Information ExchangeorAll Filesin order to find it - On the next screen, enter the password you chose in step 2.1, and pay close attention to the first check box. This determines how securely your certificate is stored, and also how convenient it is to use
- On the last screen, choose
Place all certificates in the following store. Verify that it saysPersonal, then click Finish - Repeat the import procedure above for the
Trusted Root Certification Authoritiescertificates section.
- In the
Create the port associations for your application. On Windows Vista and later, use
netsh, as I did. (For Windows XP and earlier, usehttpcfg)From the administrative command line, type the following to set up the SSL binding*to your app, and the appropriate port. NB:This command is easy to get wrong, because (in PowerShell) the braces need to be escaped. The following PowerShell command will work:
netsh http add sslcert ipport=0.0.0.0:8443 ` certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 ` appid=`{00112233-4455-6677-8899-AABBCCDDEEFF`}For
cmd.exe, the following should be used instead:netsh http add sslcert ipport=0.0.0.0:8443 certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}- The
ipportparameter will cause the SSL certificate to bind to the port8443on every network interface; to bind to a specific interface (only), choose the IP address associated with that network interface. - The
certhashis simply the certificate thumbprint, with spaces removed - The
appidis the GUID stored in the Assembly Info of your application. (Sidenote: Thenetshmechanism is evidently a COM interface, judging from this questionand its answers)
*Microsoft has redirected the SSL Bindinglink from hereto there.
- The
Start up your web-server, and you're good to go!
通过
HttpListener以下方式在 .NET 中创建独立服务器:var prefixes = {"http://localhost:8080/app/root", "https://localhost:8443/app/root"}; var listener = new HttpListener(); foreach (string s in prefixes) listener.Prefixes.Add(s); listener.Start();创建自签名证书:*
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365,这将提示您输入命令行上每个证书字段的值。对于通用名称,请输入域名(例如localhost)openssl pkcs12 -inkey bob_key.pem -in bob_cert.cert -export -out bob_pfx.pfx,以便可以在目标计算机上使用其密钥导入。
*有关使用的替代方法
makecert,请参阅 Walter 自己的回答。打开本地计算机的证书管理器。当您运行时
certmgr.msc,它会为当前用户打开证书管理器,这不是我们在这里想要的。反而:- 从目标机器上的管理命令提示符,运行
mmc - 按,或单击Ctrl+ MFile> Add/Remove Snap-in
- 选择
Certificates,然后单击Add > - 在出现的对话框中,选择
Computer Account,然后单击Next - 选择
Local Computer。点击Finish,然后Okay
- 从目标机器上的管理命令提示符,运行
将证书 (
pfx) 导入目标计算机上的Windows 证书存储区- 在
mmc之前打开的窗口中,向下钻取Certificates (Local Computer)> Personal - 右键单击
Personal,然后单击All Tasks-> Import... - 在出现的对话框的第二个屏幕中,找到并导入您的证书。您必须将文件类型过滤器更改为
Personal Information Exchange或All Files才能找到它 - 在下一个屏幕上,输入您在步骤 2.1 中选择的密码,并密切注意第一个复选框。这决定了您的证书存储的安全程度,以及使用的方便程度
- 在最后一个屏幕上,选择
Place all certificates in the following store。验证它是否显示Personal,然后单击Finish - 对
Trusted Root Certification Authorities证书部分重复上述导入过程。
- 在
为您的应用程序创建端口关联。在 Windows Vista 及更高版本上
netsh,像我一样使用 。(对于 Windows XP 及更早版本,请使用httpcfg)在管理命令行中,键入以下内容以设置与您的应用程序的SSL 绑定*以及相应的端口。 注意:此命令很容易出错,因为(在 PowerShell 中)需要对大括号进行转义。以下 PowerShell 命令将起作用:
netsh http add sslcert ipport=0.0.0.0:8443 ` certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 ` appid=`{00112233-4455-6677-8899-AABBCCDDEEFF`}对于
cmd.exe,应改为使用以下内容:netsh http add sslcert ipport=0.0.0.0:8443 certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}- 该
ipport参数将导致 SSL 证书绑定到8443每个网络接口上的端口;要绑定到特定接口(仅),请选择与该网络接口关联的 IP 地址。 - 这
certhash只是证书指纹,删除了空格 - 该
appid是存储在您的应用程序的程序集信息的GUID。(旁注:netsh从这个问题及其答案来看,该机制显然是一个 COM 接口)
- 该
启动您的网络服务器,一切顺利!
回答by Trevy Burgess
We can import the certificates using PowerShell and C# (no manual steps required).
我们可以使用 PowerShell 和 C# 导入证书(不需要手动步骤)。
For details, see: https://blog.davidchristiansen.com/2016/09/howto-create-self-signed-certificates-with-powershell/
详情见:https: //blog.davidchristiansen.com/2016/09/howto-create-self-signed-certificates-with-powershell/
I'm using this code:
我正在使用此代码:
/// <summary>
/// Create and install a self-signed certificate for HTTPS use
/// </summary>
private static void CreateInstallCert(int expDate, string password, string issuedBy)
{
// Create/install certificate
using (var powerShell = System.Management.Automation.PowerShell.Create())
{
var notAfter = DateTime.Now.AddYears(expDate).ToLongDateString();
var assemPath = Assembly.GetCallingAssembly().Location;
var fileInfo = new FileInfo(assemPath);
var saveDir = Path.Combine(fileInfo.Directory.FullName, "CertDir");
if (!Directory.Exists(saveDir))
{
Directory.CreateDirectory(saveDir);
}
// This adds certificate to Personal and Intermediate Certification Authority
var rootAuthorityName = "My-RootAuthority";
var rootFriendlyName = "My Root Authority";
var rootAuthorityScript =
$"$rootAuthority = New-SelfSignedCertificate" +
$" -DnsName '{rootAuthorityName}'" +
$" -NotAfter '{notAfter}'" +
$" -CertStoreLocation cert:\LocalMachine\My" +
$" -FriendlyName '{rootFriendlyName}'" +
$" -KeyUsage DigitalSignature,CertSign";
powerShell.AddScript(rootAuthorityScript);
// Export CRT file
var rootAuthorityCrtPath = Path.Combine(saveDir, "MyRootAuthority.crt");
var exportAuthorityCrtScript =
$"$rootAuthorityPath = 'cert:\localMachine\my\' + $rootAuthority.thumbprint;" +
$"Export-Certificate" +
$" -Cert $rootAuthorityPath" +
$" -FilePath {rootAuthorityCrtPath}";
powerShell.AddScript(exportAuthorityCrtScript);
// Export PFX file
var rootAuthorityPfxPath = Path.Combine(saveDir, "MyRootAuthority.pfx");
var exportAuthorityPfxScript =
$"$pwd = ConvertTo-SecureString -String '{password}' -Force -AsPlainText;" +
$"Export-PfxCertificate" +
$" -Cert $rootAuthorityPath" +
$" -FilePath '{rootAuthorityPfxPath}'" +
$" -Password $pwd";
powerShell.AddScript(exportAuthorityPfxScript);
// Create the self-signed certificate, signed using the above certificate
var gatewayAuthorityName = "My-Service";
var gatewayFriendlyName = "My Service";
var gatewayAuthorityScript =
$"$rootcert = ( Get-ChildItem -Path $rootAuthorityPath );" +
$"$gatewayCert = New-SelfSignedCertificate" +
$" -DnsName '{gatewayAuthorityName}'" +
$" -NotAfter '{notAfter}'" +
$" -certstorelocation cert:\localmachine\my" +
$" -Signer $rootcert" +
$" -FriendlyName '{gatewayFriendlyName}'" +
$" -KeyUsage KeyEncipherment,DigitalSignature";
powerShell.AddScript(gatewayAuthorityScript);
// Export new certificate public key as a CRT file
var myGatewayCrtPath = Path.Combine(saveDir, "MyGatewayAuthority.crt");
var exportCrtScript =
$"$gatewayCertPath = 'cert:\localMachine\my\' + $gatewayCert.thumbprint;" +
$"Export-Certificate" +
$" -Cert $gatewayCertPath" +
$" -FilePath {myGatewayCrtPath}";
powerShell.AddScript(exportCrtScript);
// Export the new certificate as a PFX file
var myGatewayPfxPath = Path.Combine(saveDir, "MyGatewayAuthority.pfx");
var exportPfxScript =
$"Export-PfxCertificate" +
$" -Cert $gatewayCertPath" +
$" -FilePath {myGatewayPfxPath}" +
$" -Password $pwd"; // Use the previous password
powerShell.AddScript(exportPfxScript);
powerShell.Invoke();
}
}
Requires PowerShell 4 or higher.
需要 PowerShell 4 或更高版本。
回答by Stefan Verhagen
As making your own self-signed certificates in the answers did not work for me and as the question specifically calls for making a .NET HTTPListener HTTPS capable and asks for any tips/advice, I want to share my approach.
由于在答案中制作您自己的自签名证书对我不起作用,并且该问题特别要求使 .NET HTTPListener 具有 HTTPS 功能并要求提供任何提示/建议,因此我想分享我的方法。
You need a hostname, something like www.made-up.com which needs to point to your WAN IP address (e.g. ask your host provider for instructions) and forward its port, e.g. 443, to your local machine. Don't forget to open that inbound 443 port in your firewall of your local machine.
您需要一个主机名,例如 www.made-up.com,它需要指向您的 WAN IP 地址(例如,向您的主机提供商询问说明)并将其端口(例如 443)转发到您的本地计算机。不要忘记在本地计算机的防火墙中打开该入站 443 端口。
I used https://letsencrypt.org/. On Windows this not as easy as on Linux, because there isn't any official certbot ACME client for windows. However, you can use https://github.com/Lone-Coder/letsencrypt-win-simple, of which there are also binaries around. However "Currently only IIS is supported". But you can easily trick it to create a certificate on your computer such that you can approach your HTTP listener the SSL way:
我使用了https://letsencrypt.org/。在 Windows 上这不像在 Linux 上那么容易,因为没有任何用于 Windows 的官方 certbot ACME 客户端。但是,您可以使用https://github.com/Lone-Coder/letsencrypt-win-simple,其中也有二进制文件。但是“目前仅支持 IIS”。但是你可以很容易地欺骗它在你的计算机上创建一个证书,这样你就可以通过 SSL 方式访问你的 HTTP 侦听器:
- Install IIS (via Windows Features on/of), create a website within IIS and assign the hostname. Also make a secure (443 port) website of it.
- Run the letsencrypt-win-simple EXE file (I used version 1.9.1). Answer the questions to let it generate the certificate.
- After that you can stop de IIS server.
- 安装 IIS(通过 Windows 功能打开/关闭),在 IIS 中创建一个网站并分配主机名。还要制作一个安全的(443 端口)网站。
- 运行letsencrypt-win-simple EXE 文件(我使用的是 1.9.1 版)。回答问题以使其生成证书。
- 之后,您可以停止 de IIS 服务器。
I believe you have to take note of the refresh task generated, since I am not sure it will succeed after a few months (you probably have to start IIS again for the certificate to be renewed).
我相信您必须注意生成的刷新任务,因为我不确定它会在几个月后成功(您可能必须再次启动 IIS 才能更新证书)。

