IIS 是否可以在不将 SSL 客户端证书映射到 windows 用户的情况下要求它们?

Can IIS require SSL client certificates without mapping them to a windows user?

我希望能够将 SSL 客户端证书映射到 ASP.NET 身份用户。我希望 IIS 完成尽可能多的工作(协商客户端证书并可能验证它是否由受信任的 CA 签名),但我不希望 IIS 将证书映射到 Windows 用户.客户端证书被传递到 ASP.NET,在那里它被检查并映射到一个 ASP.NET 身份用户,它变成了一个 ClaimsPrincipal。

到目前为止,我能够让 IIS 将客户端证书传递给 ASP.NET 的唯一方法是启用 iisClientCertificateMappingAuthentication 并设置多对一映射到Windows 帐户(之后再也不会用于任何其他用途。)有没有任何方法可以让 IIS 协商并在没有此配置步骤的情况下通过证书?

您不必使用 iisClientCertificateMappingAuthentication。客户端证书可在 HttpContext 中访问。

var clientCert = HttpContext.Request.ClientCertificate;

要么在整个站点上启用 RequireClientCertificate,要么使用单独的 login-with-clientcertificate 页面。

下面是在 ASP.NET MVC 中执行此操作的一种方法。希望您可以使用其中的一部分来满足您的具体情况。

  1. 首先确保您可以通过启用功能委托在 web.config 中设置 SslFlags。

  1. 使站点接受(但不要求)客户端证书

  2. 设置需要客户端证书的 login-with-clientcertificate-page 路径。在这种情况下,用户控制器具有 CertificateSignin 操作。

  3. 创建登录控制器(伪代码)

    [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");
    }