【问题标题】:HTTPS from a console application?来自控制台应用程序的 HTTPS?
【发布时间】:2012-05-03 16:34:24
【问题描述】:

我没有使用IIS,它甚至没有安装在这台计算机上。我的控制台中也没有任何app.config 文件或web.config 文件托管WCFREST 服务。但我想尝试在主机控制台应用程序上运行 HTTPS:

class Program
{
    static void Main(string[] args)
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        //WebHttpBinding binding = new WebHttpBinding();
        //binding.Security.Mode = WebHttpSecurityMode.Transport;
        host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
        host.Open();

        Console.WriteLine("Host opened");
        Console.ReadLine();

有没有办法让我的服务在HTTPS 中运行?

【问题讨论】:

  • stackoverflow.com/questions/3140526/wcf-https-vs-http 有一个使用 https 的示例控制台程序,它有一些关于生成用于开发的自签名证书的信息。
  • 那是 wsHttpBinding 而不是 webHttpBinding,那是纯 wcf 我的 wcf 暴露为 rest。不确定它会有所作为,但那些看起来很复杂,我不知道从哪里开始? +1 很好的发现。
  • 以下给出的答案应该为这个问题提供完整而可靠的解决方案,包括分步建议。请注意,对于在底层应用程序中应用 SSL 或 TLS 不切实际或不可能的情况,此问题存在通用解决方案 (stunnel)。这在官方解决方案无法有效运行或需要测试连接奇偶校验的情况下特别有用,因此我建议在证明有用的时候将其保留在您的技巧包中。
  • This project 做你想做的事,但不幸的是显然使用了配置文件。

标签: c# wcf web-services rest https


【解决方案1】:
  1. 创建并安装根权限和 HTTPS 证书

    以管理员身份打开命令提示符:

    创建文件夹C:\Certs 并导航到它。

    #Root Authority
    makecert.exe -r -pe -n "CN=My Root Authority" -ss CA -sr LocalMachine -a sha1 -sky signature -cy authority -sv CA.pvk CA.cer
    
    #Certificate
    makecert.exe -pe -n "CN=localhost" -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -ic CA.cer -iv CA.pvk -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -sv server.pvk server.cer
    
    #key
    pvk2pfx.exe -pvk server.pvk -spc server.cer -pfx server.pfx
    

    **makecert 和 pvk2pfx 的默认位置是 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin

  2. 安装证书

    从命令行:

    certmgr.exe -add CA.cer -r LocalMachine -s CertificateAuthority

    certmgr.exe -add server.pfx -r LocalMachine -s My -all

    来自 MMC:

    通过转到命令提示符并键入 MMC 打开MMC。这将打开空白的 MMC 控制台。单击添加/删除管理单元。添加证书并选择计算机帐户/本地计算机。

    导航到中间证书颁发机构/证书。右键单击并选择导入。导航到您已创建 CA.cer 文件的文件夹,然后单击以导入。

    导航到个人/证书并右键单击导入。找到您的 server.pfx 文件(您需要从可用扩展名列表中选择 PFX)并导入此文件。完成后,通过双击打开证书并在详细信息下记下其指纹。将此粘贴到 Notepad 并删除开头多余的 ? 并删除空格。

    要获取服务器指纹证书,您可以在PowerShell 中运行:

    $getThumb = Get-ChildItem -path cert:\LocalMachine\TrustedPeople | where { $_.Subject -match "CN=localhost" }
    $getThumb.thumbprint
    
  3. 使用netsh注册和映射WCF端口

    映射到 WCF 端口

    netsh http add sslcert ipport=0.0.0.0:8000 certhash=73269e9b554f58d75e77880f5ff72b50c8d724ee appid={e2eaacd9-92e6-43cc-b51c-7a7887149607}
    
    appid - any GUID
    certhas - this is the thumb print from the step 2
    
  4. 设置您的主机

    设置为 HTTPS 并启用传输安全性:

    string baseAddress = "https://" + Environment.MachineName + ":8000/Service";
    var binding = new WebHttpBinding();
    binding.Security.Mode = WebHttpSecurityMode.Transport;
    

详细参考

如果您在添加 sslcert 时遇到问题:

【讨论】:

  • 这只是为了让服务说话。您可以继续添加到安全堆栈,例如binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;就像任何其他非自托管服务一样。
  • 如何制作证书在哪里输入?
  • 好的,当我尝试 makecert 时显示错误:将编码的证书保存到存储失败 => 0x5 (5)
  • 如果我更改为 CURRENTUSER 而不是 localmachine 它可以工作,但是 netsh 会抛出错误参数不正确?而且我可能会冒险猜测第三个命令也不起作用。
  • 无法让它为我的一生工作......在客户端发现服务说“机器主动拒绝它或未配置证书”
【解决方案2】:

在 VS.NET 2010 中创建一个新的控制台应用程序项目。现在添加对 dll 的引用

 a.  System.ServiceModel
 b.  System.ServiceModel.Web
 c.  System.Runtime.Serialization

Program.cs Main 方法有如下代码

public class Program
    {
        public static void Main(string[] args)
        {
            Uri baseAddress = new Uri("https://"+Environment.MachineName+":54321/hello");
            using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
            {                
                WebHttpBinding web = new WebHttpBinding();
                web.Security.Mode = WebHttpSecurityMode.Transport;                
                host.AddServiceEndpoint(typeof(IHelloWorldService), web, "").Behaviors.Add(new WebHttpBehavior());                                
                host.Credentials.ServiceCertificate.Certificate = (X509Certificate2)GetX509Certificate();                               
                host.Open();
                Console.WriteLine("The service is ready at {0}", baseAddress);
                Console.WriteLine("Press <Enter> to stop the service.");
                Console.ReadLine();                
                host.Close();
            }
        }

        private static X509Certificate GetX509Certificate()
        {
            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            store.Open(OpenFlags.OpenExistingOnly);
            X509Certificate certificate = null;
            X509Certificate2Collection cers = store.Certificates.Find(X509FindType.FindBySubjectName, "localhost", false);            
            if (cers.Count > 0)
            {
                certificate = cers[0];
            }
            store.Close();
            return certificate;
        }
    }

[ServiceContract]
    public interface IHelloWorldService
    {
        [WebGet(UriTemplate="SayHello/{name}")]
        string SayHello(string name);
    }

    public class HelloWorldService : IHelloWorldService
    {
        public string SayHello(string name)
        {
            return string.Format("Hello, {0}", name);
        }
    }

现在我们通过创建以下命令的批处理文件(取自 MSDN)并从 VS.NET 命令提示符执行它来创建证书:

echo off
setlocal

call :setscriptvariables %1
IF NOT DEFINED SUPPORTED_MODE call :displayusage
IF DEFINED SUPPORTED_MODE call :cleancerts
IF DEFINED SETUP_SERVICE call :setupservice
IF DEFINED SETUP_CLIENT call :setupclient
GOTO end

:cleancerts
REM cleans up certs from previous runs.    
certmgr.exe -del -r CurrentUser -s My -c -n %CLIENT_NAME%
certmgr.exe -del -r CurrentUser -s TrustedPeople -c -n localhost
certmgr.exe -del -r LocalMachine -s My -c -n localhost
certmgr.exe -del -r LocalMachine -s TrustedPeople -c -n %CLIENT_NAME%
certmgr.exe -put -r LocalMachine -s My -c -n %COMPUTER_NAME% computer.cer
IF %ERRORLEVEL% EQU 0 (
   DEL computer.cer       
   pause
   certmgr.exe -del -r LocalMachine -s My -c -n %COMPUTER_NAME%
)

:cleanupcompleted   

GOTO :EOF

:setupclient
makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe

IF DEFINED EXPORT_CLIENT (        
    certmgr.exe -put -r CurrentUser -s My -c -n %CLIENT_NAME% client.cer
) ELSE (        
    certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople
)
GOTO :EOF

:setupservice
makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe

IF DEFINED EXPORT_SERVICE (       
    certmgr.exe -put -r LocalMachine -s My -c -n %SERVER_NAME% service.cer
) ELSE (        
    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
)
GOTO :EOF

:setscriptvariables
REM Parses the input to determine if we are setting this up for a single machine, client, or server
REM sets the appropriate name variables
call :setcomputername
IF [%1]==[] CALL :singlemachine
IF [%1]==[service] CALL :service
IF [%1]==[client] CALL :client

set CLIENT_NAME=client.com

GOTO :EOF

:singlemachine    
SET SUPPORTED_MODE=1
SET SETUP_CLIENT=1
SET SETUP_SERVICE=1
SET SERVER_NAME=localhost
GOTO :EOF

:service    
SET SUPPORTED_MODE=1
SET SETUP_SERVICE=1
SET EXPORT_SERVICE=1
SET SERVER_NAME=%COMPUTER_NAME%
GOTO :EOF

:client   
SET SUPPORTED_MODE=1
SET SETUP_CLIENT=1
SET EXPORT_CLIENT=1
GOTO :EOF

:setcomputername
REM Puts the Fully Qualified Name of the Computer into a variable named COMPUTER_NAME
for /F "delims=" %%i in ('cscript /nologo GetComputerName.vbs') do set COMPUTER_NAME=%%i
GOTO :EOF

:displayusage
ECHO Correct usage:
ECHO     Single Machine - Setup.bat
ECHO     Client Machine - Setup.bat client
ECHO     Service Machine - Setup.bat service
:end

现在打开 Microsoft 管理控制台并选择文件 --> 添加/删除管理单元以添加证书 - 当前用户和证书 - 本地机器存储

导航到证书 - 本地计算机个人存储以查找创建并安装的名为 localhost(自签名)的服务器证书。

现在打开您的 IIS 并右键单击默认网站以将 HTTPS 绑定添加到它与您在控制台应用程序中定义的端口号匹配(对于我的 54321)并选择证书为“localhost”(上述步骤中创建的证书),然后单击“确定”和“关闭”

现在启动您的控制台应用程序以运行您的服务,现在打开 fiddler 并执行 GET 请求,如图所示:

GET https://rajeshwin7:54321/hello/sayhello/rajesh HTTP/1.1
User-Agent: Fiddler
Host: rajeshwin7:54321

现在您会收到如下回复:

HTTP/1.1 200 OK
Content-Length: 90
Content-Type: application/xml; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 04 May 2012 14:51:25 GMT

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello, rajesh</string>

当没有 IIS 存在时,打开命令提示符并在命令提示符处输入以下内容,使用 winvista 及以上操作系统中的 netsh 工具和 winxp 中的 httpcfg 为 ssl 证书进行 http 端口映射。

C:\> netsh http add sslcert ipport=0.0.0.0:54321 certhash=6797aea29440de9389bc636e15a35b741d8c22a3 appid={2e80948d-9ae6-42c9-ad33-294929333965}

certhash -- 上面创建的证书的指纹 ID。指纹 id 可以通过打开 Microsoft 管理控制台来获取 - 添加/删除本地计算机上计算机帐户证书存储的管理单元,然后导航到个人存储以找到证书(假设它已按上述方式安装),然后双击证书并导航到详细信息选项卡以查找指纹 ID 作为属性之一(只需通过删除空格将其复制以在上述 netsh 命令中使用)

appid -- 是与您的应用程序关联的 guid,可以在项目属性文件夹中的 assembly.cs 文件中找到,如下所示:

现在要清理证书,使用以下命令创建一个 bathc 文件并使用 Vs.NET 命令提示符执行它:

echo off
setlocal
set CLIENT_NAME=client.com
call :setcomputername
call :cleancerts
DEL client.cer > NUL 2>&1
DEL service.cer > NUL 2>&1
GOTO end

:cleancerts
REM cleans up certs from previous runs.
certmgr.exe -del -r CurrentUser -s My -c -n %CLIENT_NAME%
certmgr.exe -del -r CurrentUser -s TrustedPeople -c -n localhost

certmgr.exe -del -r LocalMachine -s My -c -n localhost
certmgr.exe -del -r LocalMachine -s TrustedPeople -c -n %CLIENT_NAME%
certmgr.exe -put -r LocalMachine -s My -c -n %COMPUTER_NAME% computer.cer
IF %ERRORLEVEL% EQU 0 (
   DEL computer.cer
   pause
   certmgr.exe -del -r LocalMachine -s My -c -n %COMPUTER_NAME%
)

:cleanupcompleted
GOTO :EOF

:setcomputername
REM Puts the Fully Qualified Name of the Computer into a variable named COMPUTER_NAME
for /F "delims=" %%i in ('cscript /nologo GetComputerName.vbs') do set COMPUTER_NAME=%%i
GOTO :EOF

:end

您可以使用 netsh 命令删除 ssl 证书映射到端口,如下所示:

c:\> netsh http delete sslcert ipport:0.0.0.0:54321

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 2015-09-27
    相关资源
    最近更新 更多