Adding SSL Certificate via “netsh.exe” does not la

2019-05-10 10:25发布

问题:

I am currently building an ASP.Net MVC 3 eccomerce app that uses IIS Express for my development server.

As we are accepting payments via the app we need to enforce SSL connections for the checkout process.

After following Scott Hanselman's well written article on how to set up self signed SSL certificates for use with IIS Express, I can access my site via both:

  • http://localhost
  • https://localhost

This is all gravy, until I restart. It seems that each time I restart (for whatever reason) I need to run the following commands again:

netsh http delete sslcert ipport=0.0.0.0:443
netsh http add sslcert ipport=0.0.0.0:443 appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash=<thumbprint from Certificate Manager>

I have tried exporting and importing the generated certificate, as well as dragging the certificate from the Personal Store to the Trusted Root Certification Authorities. Both to no avail.

Does anyone have any ideas?

回答1:

This problem is mentioned by a few people in the comments on http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx

The final comment is:

I think by moving the self signed cert from Personal to Trusted Root CA directory causes a problem that SSL stops working after developers reboot their machines. (Don't know how it happens, but it does happen consistently.) I finally get around this issue by export and re-import the self-signed cert into the trusted root directory (instead of simply drag it over). Now my self-signed cert is considered and I don't need to REINSTALL/REPAIR IIS Express every time I reboot the machine.



回答2:

Did you import certificate to currentuser or LocalMachine store? It looks like if you import certificate to CurrentUser store this problem would arise. Take a look at the following thread http://social.msdn.microsoft.com/Forums/en/wcf/thread/9e560c64-c53a-4de5-80d5-d2231ba8bcb1



回答3:

A few comments.

First, you can get to the IIS Express thumbprint without using the MMC by using the following command:

powershell -command "& {get-childitem -path cert:\localmachine\my | where-object {$.FriendlyName -match 'IIS Express Development Certificate'} | % { $.Thumbprint}}"

As explained in http://msdn.microsoft.com/en-us/library/ms733791.aspx , you use the thumbprint in the command to netsh. You can use the above powershell technique to construct the correct netsh command for your particular installation of IIS Express.

Let's add to the above command and have it output the correct netsh command for port 443:

powershell -command "& {get-childitem -path cert:\localmachine\my | where-object {$.FriendlyName -match 'IIS Express Development Certificate'} | % { 'netsh http add sslcert ipport=0.0.0.0:443 appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash='+$.Thumbprint}}"

This will display the full netsh command that you should use. You can copy / paste it and invoke it yourself. You can also add ** | cmd.exe** to the above command to invoke it automatically. Let's do that. Below is the above PowerShell command ready for you to copy / paste into an Admin Command prompt to set bind the local 443 port to the local IIS Express certificate:

powershell -command "& {get-childitem -path cert:\localmachine\my | where-object {$.FriendlyName -match 'IIS Express Development Certificate'} | % { 'netsh http add sslcert ipport=0.0.0.0:443 appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash='+$.Thumbprint}}" | cmd.exe



回答4:

Below is a PowerShell script that can remove the existing certificate, then create and bind a new self-signed certificate to IIS 8.0 Express. The PowerShell you launch to run it must use Run as Administrator. I use it to increase my key size from the default of 1024-bit to 4096-bit.

# NOTE: This script MUST use Run as Administrator to work correctly.
# This script works with IIS 8.0 Express.
$currentIdentity=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$currentPrincipal=new-object System.Security.Principal.WindowsPrincipal($currentIdentity)
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator

if (($currentPrincipal -eq $null) -or ($currentPrincipal.IsInRole($adminRole) -eq $false))
{
    Write-Error "This script must be run with Admnistrator privileges."
    exit
}

$iisExpressAppId = "{214124cd-d05b-4309-9af9-9caa44b2b74a}"
$iisExpressCertFriendlyName = "IIS Express Development Certificate"

# Get the current IIS Express certificate and remove it if it exists
$iisExpressCert = Get-ChildItem Cert:\LocalMachine\My | ? { $_.FriendlyName -eq $iisExpressCertFriendlyName }

if ($iisExpressCert -ne $null)
{
    Remove-Item $iisExpressCert.PSPath
}

# Create a new self-signed server certificate with a 4096-bit key
& "C:\Program Files (x86)\Windows Kits\8.1\bin\x86\makecert.exe" -r -pe -n "CN=localhost" -m 60 -ss My -sr LocalMachine -sky Exchange -eku 1.3.6.1.5.5.7.3.1 -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -a sha512 -len 4096

# Get the newly generated server certificate
$iisExpressCert = Get-ChildItem Cert:\LocalMachine\My | ? { $_.Subject -eq "CN=localhost" -and [DateTime]::Parse($_.GetEffectiveDateString()).Date -eq [DateTime]::Today }

if ($iisExpressCert -ne $null)
{
    # Change the friendly name of the new certificate.
    $iisExpressCert.FriendlyName = $iisExpressCertFriendlyName

    # Iterate through the IIS Express ports removing the old certificate
    # and adding the new one.
    44300..44399 | foreach {
        & "C:\Windows\System32\netsh.exe" http delete sslcert ipport=0.0.0.0:$($_)
        & "C:\Windows\System32\netsh.exe" http add sslcert ipport=0.0.0.0:$($_) certhash=$($iisExpressCert.Thumbprint) appid=$($iisExpressAppId)
    }
}

<# Remove comment tags only if you intend to trust the self-signed cert.
# Adds the Public Certificate to the Trusted Root Certification Authorities.
$iisExpressPublicCert = Get-ChildItem Cert:\LocalMachine\AuthRoot | ? { $_.FriendlyName -eq $iisExpressCertFriendlyName }

if ($iisExpressPublicCert -ne $null)
{
    Remove-Item $iisExpressPublicCert.PSPath
}

$iisExpressPublicCert = New-Object "System.Security.Cryptography.X509Certificates.X509Certificate2" @(,$iisExpressCert.Export("Cert"))
$iisExpressPublicCert.FriendlyName = $iisExpressCertFriendlyName

$trustedCertStore = Get-Item Cert:\LocalMachine\AuthRoot
$trustedCertStore.Open("ReadWrite")
$trustedCertStore.Add($iisExpressPublicCert)
$trustedCertStore.Close()
#>