我想用 C# 实现一个简单的 HTTP 服务器/侦听器,它支持带有自签名证书的 HTTP。
先决条件
我将 EmbedIO 用于 Web 服务器。我也试过 CeenHttpd 和微软的 HttpListener 类。
创建私钥/公钥
要创建要用于 X509 证书的私钥/公钥,我在机器的 Linux 子系统 (Ubuntu) 中运行以下命令:
openssl req -new -newkey rsa:1024 -days 365 -nodes -x509 -keyout test.key -out test.cert
要将(或打包?)转换为 pfx 文件,我运行以下命令:
openssl pkcs12 -export -out test.pfx -inkey test.key -in test.cert
申请
这是我的控制台应用程序的代码:
using EmbedIO;
using EmbedIO.Actions;
using EmbedIO.Files;
using System;
using System.IO;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
namespace EmbedIoTest
{
class Program
{
public static DirectoryInfo GetExecutingDirectory()
{
var location = new Uri(Assembly.GetEntryAssembly().GetName().CodeBase);
return new FileInfo(location.AbsolutePath).Directory;
}
private static WebServer CreateWebServer(string url, int port)
{
var certificate = new X509Certificate2(@"XXX\test.pfx");
var exePath = GetExecutingDirectory();
var server = new WebServer(o => o
.WithMode(HttpListenerMode.EmbedIO)
.WithCertificate(certificate)
.WithAutoRegisterCertificate()
.WithUrlPrefix("https://*:" + port))
// First, we will configure our web server by adding Modules.
.WithStaticFolder("/", exePath.ToString(), true, m =>
{
m.WithDirectoryLister(DirectoryLister.Html).WithoutDefaultDocument().WithContentCaching(false);
})
.WithModule(new ActionModule("/", HttpVerbs.Any, ctx => ctx.SendDataAsync(new { Message = "Error" }))); ;
return server;
}
static void Main(string[] args)
{
var url = "127.0.0.1";
var port = 8080;
if (args.Length > 0)
url = args[0];
using (var server = CreateWebServer(url, port))
{
server.RunAsync();
Console.ReadKey(true);
}
}
}
}
当我以普通用户身份运行服务器时,出现错误,提示我需要以管理员身份运行应用程序才能导入证书。
如果我以管理员身份运行它,我收到错误:
<块引用>SSL 证书添加失败,错误:1312 指定的登录会话不存在。它可能已经被终止。
如果我从 WebServer 实例中删除“WithAutoRegisterCertificate()”行,控制台应用程序将启动。但是当我通过 CURL 或 Postman 调用端点时,我没有得到任何响应。
邮递员输出:
<块引用>错误:在建立安全 TLS 连接之前客户端网络套接字已断开
卷曲输出:
<块引用>curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL 连接到 127.0.0.1:8080
解决方案
我需要的是一个支持 HTTPS 的简单 HTTP 服务器。就这样。但它应该独立于 IIS / Apache / nginx 等运行。有没有简单的方法来实现这一点?