Can IIS require SSL client certificates without ma

2020-03-28 03:27发布

问题:

I want to be able to map SSL client certificates to ASP.NET Identity users. I would like IIS to do as much of the work as possible (negotiating the client certificate and perhaps validating that it is signed by a trusted CA), but I don't want IIS to map the certificate to a Windows user. The client certificate is passed through to ASP.NET, where it is inspected and mapped to an ASP.NET Identity user, which is turned into a ClaimsPrincipal.

So far, the only way I have been able to get IIS to pass the client certificate through to ASP.NET is to enable iisClientCertificateMappingAuthentication and set up a many-to-one mapping to a Windows account (which is then never used for anything else.) Is there any way to get IIS to negotiate and pass the certificate through without this configuration step?

回答1:

You do not have to use the iisClientCertificateMappingAuthentication. The client certificate is accessible in the HttpContext.

var clientCert = HttpContext.Request.ClientCertificate;

Either you enable RequireClientCertificate on the complete site or use a separate login-with-clientcertificate page.

Below is one way of doing this in ASP.NET MVC. Hopefully you can use parts of it to fit your exact situation.

  1. First make sure you are allowed to set the SslFlags in web.config by turning on feature delegation.

  1. Make site accept (but not require) Client Certificates

  2. Set path to login-with-clientcertificate-page where client certificates will be required. In this case a User controller with a CertificateSignin action.

  3. Create a login controller (pseudo-code)

    [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
    [AllowAnonymous()]
    public ActionResult CertificateSignIn()
    {
        //Get certificate
        var clientCert = HttpContext.Request.ClientCertificate;
    
        //Validate certificate
        if (!clientCert.IsPresent || !clientCert.IsValid)
        {
            ViewBag.LoginFailedMessage = "The client certificate was not present or did not pass validation";
            return View("Index");
        }
    
        //Call your "custom" ClientCertificate --> User mapping method.
        string userId;
        bool myCertificateMappingParsingResult = Helper.MyCertificateMapping(clientCert, out userId);
    
        if (!myCertificateMappingParsingResult)
        {
            ViewBag.LoginFailedMessage = "Your client certificate did not map correctly";
        }
        else
        {
            //Use custom Membersip provider. Password is not needed!
            if (Membership.ValidateUser(userId, null))
            {
                //Create authentication ticket
                FormsAuthentication.SetAuthCookie(userId, false);
                Response.Redirect("~/");
            }
            else
            {
                ViewBag.LoginFailedMessage = "Login failed!";
            }
        }
    
        return View("Index");
    }