在OnAuthorization无证书(HttpActionContext ActionContex

2019-10-29 16:31发布

我从这个例子创建CertificateTestController和ValuesController 如何使用客户端证书进行身份验证,并在Web API授权 。 如果您向下滚动到来自用户Ogglas“更新”。 我采取了他的榜样,并得到“CertificateTestController”的工作,我可以从我的店里抢了证书,并把它添加到“处理程序”。 当我打电话“ValuesController”,没有通过被初始化证书

X509Certificate2 cert = actionContext.Request.GetClientCertificate();

下面是我的完整代码

ValuesController

{
    [RequireSpecificCert]
    public class ValuesController : ApiController
    {
        // GET api/values
        public IHttpActionResult Get()
        {
            return Ok("It works!");
        }

        public class RequireSpecificCertAttribute : AuthorizationFilterAttribute
        {
            public override void OnAuthorization(HttpActionContext actionContext)
            {

                if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
                {
                    actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
                    {
                        ReasonPhrase = "HTTPS Required"
                    };
                }
                else
                {
                    X509Certificate2 cert = actionContext.Request.GetClientCertificate();
                    X509Certificate2 cert2 = actionContext.RequestContext.ClientCertificate;

                    if (cert == null)
                    {
                        actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
                        {
                            ReasonPhrase = "Client Certificate Required"
                        };
                    }
                    else
                    {
                        X509Chain chain = new X509Chain();

                        //Needed because the error "The revocation function was unable to check revocation for the certificate" happened to me otherwise
                        chain.ChainPolicy = new X509ChainPolicy()
                        {
                            RevocationMode = X509RevocationMode.NoCheck,
                        };
                        try
                        {
                            var chainBuilt = chain.Build(cert);
                            Debug.WriteLine(string.Format("Chain building status: {0}", chainBuilt));

                            var validCert = CheckCertificate(chain, cert);

                            if (chainBuilt == false || validCert == false)
                            {
                                actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
                                {
                                    ReasonPhrase = "Client Certificate not valid"
                                };
                                foreach (X509ChainStatus chainStatus in chain.ChainStatus)
                                {
                                    Debug.WriteLine(string.Format("Chain error: {0} {1}", chainStatus.Status, chainStatus.StatusInformation));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());
                        }
                    }

                    base.OnAuthorization(actionContext);
                }
            }

            private bool CheckCertificate(X509Chain chain, X509Certificate2 cert)
            {
                var rootThumbprint = WebConfigurationManager.AppSettings["rootThumbprint"].ToUpper().Replace(" ", string.Empty);

                var clientThumbprint = WebConfigurationManager.AppSettings["clientThumbprint"].ToUpper().Replace(" ", string.Empty);

                //Check that the certificate have been issued by a specific Root Certificate
                var validRoot = chain.ChainElements.Cast<X509ChainElement>().Any(x => x.Certificate.Thumbprint.Equals(rootThumbprint, StringComparison.InvariantCultureIgnoreCase));

                //Check that the certificate thumbprint matches our expected thumbprint
                var validCert = cert.Thumbprint.Equals(clientThumbprint, StringComparison.InvariantCultureIgnoreCase);

                return validRoot && validCert;
            }
        }

主叫以上ValuesController下面CertificateTestController

{
    [RoutePrefix("api/certificatetest")]
    public class CertificateTestController : ApiController
    {
        public IHttpActionResult Get()
        {
            var handler = new WebRequestHandler();
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.ClientCertificates.Add(GetClientCert());
            handler.UseProxy = false;
            var client = new HttpClient(handler);
            var result = client.GetAsync("https://localhost:44301//values").GetAwaiter().GetResult();
            var resultString = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
            return Ok(resultString);
        }

        private static X509Certificate GetClientCert()
        {
            X509Store store = null;
            try
            {
                store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
                store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);

                var certificateSerialNumber = "2bc034466b6960d2fee84d86e6c2532a".ToUpper().Replace(" ", string.Empty);

                var cert = store.Certificates.Cast<X509Certificate>().FirstOrDefault(x => x.GetSerialNumberString().Equals(certificateSerialNumber, StringComparison.InvariantCultureIgnoreCase));
                return cert;
            }
            finally
            {
                store.Close();
            }
        }
    }
}

请帮忙!

Answer 1:

下面是我相处时,我试图解决这一问题的方式回答问题/问题。

Q1。

为什么没有我的证书获取到客户端(代码)?

A1。

VS做的OnAuthorization(HttpActionContext ActionContext中),即使被击中之前发生的一个初始SSL协商。 在这一点上,服务器搜索在已安装验证私钥证书存储客户端证书。 如果没有私钥,然后失败。 我通过打开详细的发现问题。 请参考下面。

下面是一些需要是为了得到这个工作的改变配置。

1. Web配置文件修改

•SSL协商

下面的配置告诉Visual Studio中有一个SSL协商预计“API /值” URL。 这有助于我们限制在何时何地被证明谈判的预期。 位置路径属性

<location path="api/values">
  <system.webServer>
     <security>
        <access sslFlags="SslNegotiateCert" />
        <authentication>
          <iisClientCertificateMappingAuthentication enabled="true">
          </iisClientCertificateMappingAuthentication>
        </authentication>
      </security>
    </system.webServer>
  </location>

•证书冗长

下面的诊断故障排除过程中帮助我们,并吐出可能与证书验证会造成任何问题。

<system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.Net">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
      <source name="System.Net.HttpListener">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
      <source name="System.Net.Sockets">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
      <source name="System.Net.Cache">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="System.Net"
       type="System.Diagnostics.TextWriterTraceListener"
       initializeData="System.Net.trace.log"
       traceOutputOptions = "ProcessId, DateTime"/>
    </sharedListeners>
    <switches>
      <add name="System.Net" value="Verbose" />
      <add name="System.Net.Sockets" value="Verbose" />
      <add name="System.Net.Cache" value="Verbose" />
      <add name="System.Net.HttpListener" value="Verbose" />
    </switches>
  </system.diagnostics>

•应用程序设置

更改rootThumbprint值到任何服务器证书的指纹是和clientThumprint将任何客户端证书指纹是。 ceritificateSerialNumber应该是即将离任的证书序列号。

<appSettings>
            <add key="webpages:Version" value="3.0.0.0" />
            <add key="webpages:Enabled" value="false" />
            <add key="ClientValidationEnabled" value="true" />
            <add key="UnobtrusiveJavaScriptEnabled" value="true" />
            <add key="rootThumbprint" value="change"/>
            <add key="clientThumbprint" value="change"/>
<add key="certificateSerialNumber" value="change"/>
</appSettings>

2.本地Visual Studio和IIS快递

1)对ApplicationHost.config

路径的Visual Studio早于2015年,但2008年之后的位置 - > C:\用户\ E·\文档\ IISExpress \ Config中的Visual Studio 2015年和2017年{} PROJECT_NAME .VS \设置\ config.host.config
变化确保下面的属性设置为“允许”

2)启用SSL

启用在Visual Studio属性窗口SSL。 这是因为URL变化从HTTP到HTTPS重要。

3)WebApiConfig.cs

创建一个类的过滤器文件夹。 适当命名。 证书验证需要是非常首先检查其他任何代码都跑了。 这是WebApiConfig.cs就派上用场了。 例如,我打电话给我的类RequireHttpsAttribute。 为了运行检查只是把下面的线WebApiConfig.cs config.Filters.Add(新RequireHttpsAttribute());

4)CertificateTestController.cs

这是类作为客户端。 这个类用于将证书与请求连接,并发送出去。 有一个在这个类中的一个变化。 这是只在本地计算机上进行测试。 VAR结果= client.GetAsync( “ HTTPS://本地主机:44300个// // API值 ”).GetAwaiter()调用getResult(); 更改URL。 我们都基于下面的序列号安装证书。 证书还可以附加基于关Thumprint,主题,过期/撤销,链验证等的

var certificateSerialNumber = WebConfigurationManager.AppSettings["certificateSerialNumber"].ToUpper().Replace(" ", string.Empty);

5)ValueController.cs

此类充当服务器。 这是证书验证发生。 有在“CheckCertificate”方法/函数指webApiConfig.cs两个变化。 如果您是由下WebApiConfig.cs上述应用程序设置的变化,那么你是好去。

3.文件

1)CertificateTestController.cs

2)ValuesController.cs



文章来源: No Certificate in OnAuthorization(HttpActionContext actionContext)