Serving SSL in both Kestrel and IIS Integration modes

综合编程 2017-07-08

I’ve previously blogged about dealing with SSL
in a .NET Core application. Well, I wanted to expand upon this a bit when debugging in Visual Studio 2017. In the case of working with a development environment, this needs to tie into the launch profiles. Without handling this properly, IISExpress integration is broken which becomes an annoyance.

Based on the launch profile chosen, we may or may not want Kestrel to serve HTTPS content. We need to detect, then, if we are using an externally hosted (IIS/Nginx) proxy, within our IDE hosting environment with IISExpres proxy, or simply using Kestrel. The latter condition is the one in which we want to attach an SSL cert to Kestrel and tell it to use it.

First, I added environment variables to each of my launch profiles. I use these to easily determine which launch profile was used in my IDE. The environment variable I added is called “LAUNCH_PROFILE.”

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:8111/",
      "sslPort": 44111
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "https://localhost:44111/",
      "environmentVariables": {
        "LAUNCH_PROFILE": "IISExpress",
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "MyProject.Web": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "https://localhost:44111",
      "environmentVariables": {
        "LAUNCH_PROFILE": "Kestrel",
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

The nice thing about injecting environment variables with the launch profiles is that they will only exist when debugging within Visual Studio. Secondly, there is the “hosting.json” that configures which ports on which Kestrel will listen. Incidentally, this file does not get deployed by “dotnet publish” which makes it a good candidate to use as one of our conditions. If it doesn’t exist, then we have some assurance that we are not within our local IDE any more.

{
  "urls": "http://*:5000;https://localhost:44111"
}

Tying it all together, our Program.cs will use these elements/conditions to determine the (3) cases previously mentioned:

  • Are we running in a web proxy environment?
  • Are we running in the debugger with IISExpress proxy integration?
  • Are we running solely with Kestrel in the debugger?

The Program.cs then looks like this:

public class Program
{
    public static void Main(string[] args)
    {
        string env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        string launch = Environment.GetEnvironmentVariable("LAUNCH_PROFILE");

Grab the environment variables and then perform our comparisons If all conditions are true, we are running Kestrel and want it to use HTTPS..

IWebHost host = null;

        if (string.Equals(env, "Development", StringComparison.OrdinalIgnoreCase) &&
            string.Equals(launch, "Kestrel", StringComparison.OrdinalIgnoreCase) &&
            File.Exists($"{Directory.GetCurrentDirectory()}/{@"Properties/hosting.json"}"))
        {
            var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile(@"Properties/hosting.json", optional: false, reloadOnChange: true)
            .Build();

This section is parsing out the HTTPS port so that we can launch the browser.

var regEx = new Regex(@"((http[s]?)://)([wd.]*)(?::d+)");
            var rootUrl = regEx.Match(config["urls"]).Value;

            host = new WebHostBuilder()
                .UseConfiguration(config)
                .UseKestrel(options => options.UseHttps(new X509Certificate2("testCert.pfx", "testPassword")))
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup()
                .UseIISIntegration()
                .Build();

            OpenBrowser(rootUrl);
        }

Our else condition is to launch Kestrel normally without HTTPS/SSL integration. This will allow it to behave properly with whatever proxy we put in front of it.

else
        {
            host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup()
                .UseIISIntegration()
                .Build();
        }
        host.Run();
    }

Finally, this is a helper method I have for launching the OS’s browser. It’s helpful if using “dotnet run.”

public static void OpenBrowser(string url)
    {
        try
        {
            Process.Start(url);
        }
        catch
        {
            // hack because of this: https://github.com/dotnet/corefx/issues/10361
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                url = url.Replace("&", "^&");
                Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true });
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                Process.Start("xdg-open", url);
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                Process.Start("open", url);
            }
            else
            {
                throw;
            }
        }
    }
}

您可能感兴趣的

IIS做反向代理时Cookie域的设置 IIS通过URL重写可以实现反向代理,通过简单的配置即可以将请求转发到其它内部站点。 此时被代理的所有站点的cookie的域(domain)会自动设置为提供反向代理功能的站点的域,这一般来说没有问题。但是在多站点共享cookie时会存在问题。 比如有一个对外的域名 proxy.firefly...
Easy SSL Encryption with Certbot If you're reading this post onNixMash.com and look up to the address bar you'll see a lovely Secure designation and a web address starting with https...
How to configure Nginx SSL/TLS passthrough with TC... H ow do I configure SSL/TLS pass through on Nginx load balancer running on Linux or Unix-like system? How do I load balance TCP traffic and s...
Make SSL boring again It may (or may not!) come as surprise, but a few months ago we migrated Cloudflare’s edge SSL connection termination stack to use BoringSSL : Google'...
提高 10 倍性能:优化静态网站 几个月前,我在国外旅行,想给朋友看我个人(静态)网站上的一个链接。我试着浏览我的网站,但花费的时间比我预期的要长。网站绝对没有任何动态内容--只有动画和一些响应式设计,而且内容始终保持不变。 我对结果感到震惊,DOMContentLoaded 要 4 s,整个页面加载要 6.8 s。有 20 项关...