我有ASP.NET MVC网站,我配置为通过Active Directory联合身份验证服务进行身份验证。一切正常,直到我尝试启用令牌加密。像往常一样,我在IIS上创建了一个自签名证书,将其添加到我的Web服务器和ADFS服务器上的“受信任的根”权限,并运行应用程序以使其非常有效。
我的应用程序正确地将我重定向到ADFS服务页面以输入凭据。但是,当我提交登录名和密码时,我立即得到了{" An error occured
"消息在同一登录页面上,但没有非常有用的详细信息部分:
Activity ID: 00000000-0000-0000-b039-0080010000e4
Relying party: [My relying party name]
Error time: Fri, 21 Oct 2016 18:48:24 GMT
Cookie: enabled
User agent string: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36
之后我没有被重定向到我的网站,而且网络面板不包含任何请求。
但我发现,如果我将以下设置添加到我的网站的web.config中,它会再次开始工作:
<certificateValidation certificateValidationMode="None" />
因此,错误必须与我的证书是自签名的事实有关。但我已将它添加到Web服务器和ADFS服务器上的受信任的根权限(以及其他一些&#34;可疑的&#34;证书)。
是否有人知道可能缺少哪些内容?我可以做些什么来使我的测试环境使用自签名证书,同时验证证书链?
答案 0 :(得分:0)
我使用api处理程序执行类似操作,该处理程序充当传递,并且必须询问证书。
可能有助于您进行问题排查的内容。
将证书验证回调设置为:
// validate server cert
ServicePointManager.ServerCertificateValidationCallback += ValidateServerCertificate;
然后在验证方法中,您可以询问链:
private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// default validation bool to false
var isValid = false;
// If the certificate is a valid, signed certificate, return true to short circuit any add'l processing.
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true;
}
else
{
// cast cert as v2 in order to expose thumbprint prop
var requestCertificate = (X509Certificate2)certificate;
// init string builder for creating a long log entry
var logEntry = new StringBuilder();
// capture initial info for the log entry
logEntry.AppendFormat("Certificate Validation Error - SSL Policy Error: {0} - Cert Issuer: {1} - SubjectName: {2}",
sslPolicyErrors.ToString(),
requestCertificate.Issuer,
requestCertificate.SubjectName.Name);
//init special builder for thumprint mismatches
var thumbprintMismatches = new StringBuilder();
// load valid certificate thumbs for comparison later
var validThumbprints = new string[] { "thumbprint A", "thumbprint N" };
// else if a cert name mismatch then assume api pass thru issue and verify thumb print
if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch)
{
// compare thumbprints
var hasMatch = validThumbprints.Contains(requestCertificate.Thumbprint, StringComparer.OrdinalIgnoreCase);
// if match found then we're valid so clear builder and set global valid bool to true
if (hasMatch)
{
thumbprintMismatches.Clear();
isValid = true;
}
// else thumbprint did not match so append to the builder
else
{
thumbprintMismatches.AppendFormat("|Thumbprint mismatch - Issuer: {0} - SubjectName: {1} - Thumbprint: {2}",
requestCertificate.Issuer,
requestCertificate.SubjectName.Name,
requestCertificate.Thumbprint);
}
}
// else if chain issue, then iterate over the chain and attempt find a matching thumbprint
else if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors) //Root CA problem
{
// check chain status and log
if (chain != null && chain.ChainStatus != null)
{
// check errors in chain and add to log entry
foreach (var chainStatus in chain.ChainStatus)
{
logEntry.AppendFormat("|Chain Status: {0} - {1}", chainStatus.Status.ToString(), chainStatus.StatusInformation.Trim());
}
// check for thumbprint mismatches
foreach (var chainElement in chain.ChainElements)
{
// compare thumbprints
var hasMatch = validThumbprints.Contains(chainElement.Certificate.Thumbprint, StringComparer.OrdinalIgnoreCase);
// if match found then we're valid so break, clear builder and set global valid bool to true
if (hasMatch)
{
thumbprintMismatches.Clear();
isValid = true;
break;
}
// else thumbprint did not match so append to the builder
else
{
thumbprintMismatches.AppendFormat("|Thumbprint mismatch - Issuer: {0} - SubjectName: {1} - Thumbprint: {2}",
chainElement.Certificate.Issuer,
chainElement.Certificate.SubjectName.Name,
chainElement.Certificate.Thumbprint);
}
}
}
}
// if still invalid and thumbprint builder has items, then continue
if (!isValid && thumbprintMismatches != null && thumbprintMismatches.Length > 0)
{
// append thumbprint entries to the logentry as well
logEntry.Append(thumbprintMismatches.ToString());
}
// log as WARN here and not ERROR - if method ends up returning false then it will bubble up and get logged as an ERROR
LogHelper.Instance.Warning((int)ErrorCode.CertificateValidation, logEntry.ToString().Trim());
}
// determine env
var isDev = EnvironmentHelper.IsDevelopment();
var isTest = EnvironmentHelper.IsTest();
// if env is dev or test then ignore cert errors and return true (reference any log entries created from logic above for troubleshooting)
if (isDev || isTest)
isValid = true;
return isValid;
}
注意:您需要禁用/更改部分自定义代码 - 指纹内容,日志记录等。
答案 1 :(得分:0)
将证书添加到CA受信任存储区只意味着您信任证书的颁发者,在这种情况下证书本身就是证书本身,因为它是自签名证书。缺少的是证书验证执行链检查和撤销检查,并且两个检查中的任何一个检查失败。请注意,即使您信任证书,它仍然可以在最近被撤销,因此不应该被信任。因此,始终需要进行撤销检查。对于测试,禁用吊销检查是一种方法。一个ADFS端,您可以禁用每个依赖方的撤销检查。如果检查发生在您自己的代码上,您可以完全禁用检查或使用Stinky Towel的代码来选择性地仅允许某些证书。
答案 2 :(得分:0)
似乎要解决错误,只需在我的网络服务器上添加ADFS令牌签名证书作为受信任的根证书颁发机构。
PS:我不确定为什么令牌签名证书链验证在加密被禁用时不会引发错误,以及它与加密有什么关系,但事实如此是因为它对我们用于测试的两种环境都有帮助。