C# OnAuthorization(HttpActionContext)中没有证书
我已经从这个示例创建了CertificateTestController和ValuesController . 如果您从用户Ogglas向下滚动到“更新”。我以他为例,让“CertificateTestController”工作,在那里我可以从我的存储中获取证书并将其添加到“处理程序”中。当我调用“ValuesController”时,没有证书被初始化C# OnAuthorization(HttpActionContext)中没有证书,c#,security,asp.net-web-api,ssl-certificate,client-certificates,C#,Security,Asp.net Web Api,Ssl Certificate,Client Certificates,我已经从这个示例创建了CertificateTestController和ValuesController . 如果您从用户Ogglas向下滚动到“更新”。我以他为例,让“CertificateTestController”工作,在那里我可以从我的存储中获取证书并将其添加到“处理程序”中。当我调用“ValuesController”时,没有证书被初始化 X509Certificate2 cert = actionContext.Request.GetClientCertificate(); 这
X509Certificate2 cert = actionContext.Request.GetClientCertificate();
这是我拥有的完整代码
值控制器
{
[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;
}
}
{
[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();
}
}
}
}
{
[要求特定证书]
公共类值控制器:ApiController
{
//获取api/值
public IHttpActionResult Get()
{
返回Ok(“它工作了!”);
}
公共类RequireSpecificCertAttribute:AuthorizationFilterAttribute
{
授权时的公共覆盖无效(HttpActionContext actionContext)
{
if(actionContext.Request.RequestUri.Scheme!=Uri.UriSchemeHttps)
{
actionContext.Response=新的HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
{
ReasonPhrase=“需要HTTPS”
};
}
其他的
{
X509Certificate2Cert=actionContext.Request.GetClientCertificate();
X509Certificate2 cert2=actionContext.RequestContext.ClientCertificate;
如果(证书==null)
{
actionContext.Response=新的HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
{
ReasonPhrase=“需要客户端证书”
};
}
其他的
{
X509Chain chain=新的X509Chain();
//需要,因为“吊销功能无法检查证书的吊销”错误发生在我身上
chain.ChainPolicy=new X509ChainPolicy()
{
RevocationMode=X509RevocationMode.NoCheck,
};
尝试
{
var chainbuild=chain.Build(证书);
WriteLine(string.Format(“链构建状态:{0}”,chainbuilded));
var validCert=检查证书(链、证书);
if(chainbuild==false | | validCert==false)
{
actionContext.Response=新的HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
{
ReasonPhrase=“客户端证书无效”
};
foreach(X509ChainStatus chainStatus在chain.chainStatus中的chainStatus)
{
WriteLine(string.Format(“链错误:{0}{1}”,chainStatus.Status,chainStatus.StatusInformation));
}
}
}
捕获(例外情况除外)
{
Debug.WriteLine(例如ToString());
}
}
基于授权(actionContext);
}
}
私人bool检查证书(X509Chain chain,X509Certificate2证书)
{
var rootThumbprint=WebConfigurationManager.AppSettings[“rootThumbprint”].ToUpper().Replace(“,string.Empty);
var clientThumbprint=WebConfigurationManager.AppSettings[“clientThumbprint”].ToUpper().Replace(“,string.Empty);
//检查证书是否由特定的根证书颁发
var validRoot=chain.ChainElements.Cast().Any(x=>x.Certificate.Thumbprint.Equals(rootThumbprint,StringComparison.InvariantCultureIgnoreCase));
//检查证书指纹是否与预期指纹匹配
var validCert=cert.Thumbprint.Equals(clientThumbprint,StringComparison.invariantCultureInogoreCase);
返回validRoot&&validCert;
}
}
使用下面的CertificateTestController调用上面的值控制器
{
[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;
}
}
{
[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();
}
}
}
}
{
[RoutePrefix(“api/certificatetest”)]
公共类CertificateTestController:ApiController
{
public IHttpActionResult Get()
{
var handler=新的WebRequestHandler();
handler.ClientCertificateOptions=ClientCertificateOptions.Manual;
Add(GetClientCert());
handler.UseProxy=false;
var client=新的HttpClient(处理程序);
var result=client.GetAsync(“https://localhost:44301//values).GetAwaiter().GetResult();
var resultString=result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
返回Ok(结果字符串);
}
私有静态X509证书GetClientCert()
{
X509Store=null;
尝试
{
store=new X509Store(StoreName.My,StoreLocation.LocalMachine);
store.Open(OpenFlags.openingonly | OpenFlags.ReadOnly);
var certificateSerialNumber=“2BC03446B6960D2fee84D86E6C2532A”.ToUpper().Replace(“,string.Empty”);
var cert=store.Certificates.Cast().FirstOrDefault(x=>x.GetSerialNumberString().Equals(certificateSerialNumber,StringComparison.InvariantCultureIgnoreCase));
返回证书;
}
最后
{
store.Close();
}
}
}
}
请帮助!以下是我在试图解决问题的过程中回答的问题
<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>
var certificateSerialNumber = WebConfigurationManager.AppSettings["certificateSerialNumber"].ToUpper().Replace(" ", string.Empty);