Ssl NSUrlSession:仅当还需要客户端证书时,质询NSURAuthenticationMethodServerTrust才会失败

Ssl NSUrlSession:仅当还需要客户端证书时,质询NSURAuthenticationMethodServerTrust才会失败,ssl,xamarin.ios,nsurlsession,nsurlsessiondatatask,Ssl,Xamarin.ios,Nsurlsession,Nsurlsessiondatatask,我们希望将应用程序连接到IIS Web服务。我们使用自签名证书和客户端证书进行身份验证 当webservice不需要客户端证书身份验证时,一切正常,调用nsurAuthenticationMethodServerTrust并继续请求。 但是,当我在服务器上激活客户端证书身份验证时,在使用NSURLAuthenticationMethodServerTrust作为质询的DidReceiveChallenge之后,会调用DidCompleteWithError。错误消息是:“此服务器的证书无效。您可

我们希望将应用程序连接到IIS Web服务。我们使用自签名证书和客户端证书进行身份验证

当webservice不需要客户端证书身份验证时,一切正常,调用nsurAuthenticationMethodServerTrust并继续请求。 但是,当我在服务器上激活客户端证书身份验证时,在使用NSURLAuthenticationMethodServerTrust作为质询的DidReceiveChallenge之后,会调用DidCompleteWithError。错误消息是:“此服务器的证书无效。您可能正在连接假装为“192.168.221.118”的服务器,这可能会使您的机密信息处于危险之中

注意:“NSURLAuthenticationMethodClientCertificate”从未被调用,应用程序在此之前崩溃。 客户端证书由中间证书签名,因此我不理解ServerTrust质询失败的原因

另外:在我看来,这是不必要的,但我也尝试将客户证书添加到Sectrust的AnchorCertificates集合中

提前感谢你的帮助

这是我的密码:

private class SessionDelegate : NSUrlSessionDataDelegate, INSUrlSessionDelegate
        {
            private Action<bool, string> completed_callback;
            private string antwortCache;
            private int status_code;

            public SessionDelegate(Action<bool, string> completed)
            {
                completed_callback = completed;
                antwortCache = "";
            }
public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action<NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
            {
                if (challenge.PreviousFailureCount == 0)
                {
                    if (challenge.ProtectionSpace.AuthenticationMethod.Equals("NSURLAuthenticationMethodServerTrust"))
                    {
// GetParent is correct, because I'm too lazy to copy the certs into to the correct folders...

                        var path = Directory.GetParent(GlobaleObjekte.SSLZertifikatePath);
                        var caPath = Path.Combine(path.FullName, "ca.cert.der");
                        var caByteArray = File.ReadAllBytes(caPath);
                        var caCert = new X509Certificate2(caByteArray);

                        var interPath = Path.Combine(path.FullName, "intermediate.cert.der");
                        var interByteArray = File.ReadAllBytes(interPath);
                        var interCert = new X509Certificate2(interByteArray);

                        var secTrust = challenge.ProtectionSpace.ServerSecTrust;

                        var certCollection = new X509CertificateCollection();
                        certCollection.Add(caCert);
                        certCollection.Add(interCert);

                        secTrust.SetAnchorCertificates(certCollection);
                        var credential = new NSUrlCredential(secTrust);
                        completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);

                        return;
                    }

                    if (challenge.ProtectionSpace.AuthenticationMethod.Equals("NSURLAuthenticationMethodClientCertificate"))
                    {
                        var path = Directory.GetParent(GlobaleObjekte.SSLZertifikatePath);
                        var certPath = Path.Combine(path.FullName, "client.pfx");
                        var certByteArray = File.ReadAllBytes(certPath);
                        var cert = new X509Certificate2(certByteArray, Settings.WSClientCertPasswort);

                        var ident = SecIdentity.Import(certByteArray, Settings.WSClientCertPasswort);
                        var credential = new NSUrlCredential(ident, new SecCertificate[] { new SecCertificate(cert) }, NSUrlCredentialPersistence.ForSession); 
                       completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
                        return;
                    }

                    if (challenge.ProtectionSpace.AuthenticationMethod.Equals("NSURLAuthenticationMethodHTTPBasic"))
                    {
                        var credential = new NSUrlCredential(Settings.WebserviceBenutzer, Settings.WebservicePasswort, NSUrlCredentialPersistence.ForSession);
         completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
                        return;
                    }

                    completed_callback(false, "Unbekannte Authentifizierungsanfrage: " + challenge?.ProtectionSpace?.AuthenticationMethod);
                }
                else
                {
                    completed_callback(false, "Authentifizierung fehlgeschlagen: " + challenge?.ProtectionSpace?.AuthenticationMethod);
                }
            }
}
私有类SessionDelegate:NSUrlSessionDataDelegate,InsuralSessionDelegate
{
私人行动完成(u回调);;
私有字符串antwortCache;
专用int状态代码;
公共会话Legate(操作已完成)
{
已完成的回调=已完成;
antwortCache=“”;
}
public override void DidReceiveChallenge(NSUrlSession会话、NSUrlSessionTask任务、NSURAuthenticationChallenge挑战、Action completionHandler)
{
if(challenge.PreviousFailureCount==0)
{
if(challenge.ProtectionSpace.AuthenticationMethod.Equals(“nsurAuthenticationMethodServerTrust”))
{
//GetParent是正确的,因为我太懒了,无法将证书复制到正确的文件夹中。。。
var path=Directory.GetParent(GlobaleObjekte.SSLZertifikatePath);
var caPath=Path.Combine(Path.FullName,“ca.cert.der”);
var caByteArray=File.ReadAllBytes(caPath);
var caCert=新的X509Certificate2(caByteArray);
var interPath=Path.Combine(Path.FullName,“intermediate.cert.der”);
var interByteArray=File.ReadAllBytes(interPath);
var interCert=新的X509Certificate2(跨字节数组);
var secTrust=challenge.ProtectionSpace.ServerSecTrust;
var certCollection=new X509CertificateCollection();
certCollection.Add(caCert);
certCollection.Add(插入);
部门信任。SetAnchorCertificates(certCollection);
var凭证=新NSUrlCredential(扇区信任);
completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential,credential);
返回;
}
if(challenge.ProtectionSpace.AuthenticationMethod.Equals(“NSURLAuthenticationMethodClientCertificate”))
{
var path=Directory.GetParent(GlobaleObjekte.SSLZertifikatePath);
var certPath=Path.Combine(Path.FullName,“client.pfx”);
var certByteArray=File.ReadAllBytes(certPath);
var cert=new X509Certificate2(certByteArray,Settings.WSClientCertPasswort);
var ident=SecIdentity.Import(certByteArray,Settings.WSClientCertPasswort);
var-credential=new-NSUrlCredential(ident,new-SecCertificate[]{new-SecCertificate(cert)},NSUrlCredentialPersistence.ForSession);
completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential,credential);
返回;
}
if(challenge.ProtectionSpace.AuthenticationMethod.Equals(“nsurAuthenticationMethodHttpBasic”))
{
var credential=新的NSUrlCredential(Settings.WebserviceBenutzer、Settings.WebservicePasswort、NSUrlCredentialPersistence.ForSession);
completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential,credential);
返回;
}
已完成的_回调(false,“unbekannette authenticfizierungsanfrage:+challenge?.ProtectionSpace?.AuthenticationMethod”);
}
其他的
{
已完成的_回调(false,“Authentifizierung fehlgeschlagen:“+challenge?.ProtectionSpace?.AuthenticationMethod”);
}
}
}

我终于找到了一个解决方案。我必须以不同的方式创建凭证对象。我没有将证书添加到SecTrust并使用SecTrust作为参数创建凭证,而是必须从客户端证书创建一个标识,然后使用标识和其他证书作为参数创建凭证卢比:

 if (challenge.ProtectionSpace.AuthenticationMethod.Equals("NSURLAuthenticationMethodServerTrust"))
                    {
                        var path = Directory.GetParent(GlobaleObjekte.SSLZertifikatePath);
                        var caPath = Path.Combine(path.FullName, "ca.cert.der");
                        var caByteArray = File.ReadAllBytes(caPath);
                        var caCert = new SecCertificate(caByteArray);

                        var interPath = Path.Combine(path.FullName, "intermediate.cert.der");
                        var interByteArray = File.ReadAllBytes(interPath);
                        var interCert = new SecCertificate(interByteArray);

                        var clientPath = Path.Combine(path.FullName, "client.pfx");
                        var clientByteArray = File.ReadAllBytes(clientPath);
                        var clientCert = new X509Certificate2(clientByteArray, Settings.WSClientCertPasswort);

                        //var secTrust = challenge.ProtectionSpace.ServerSecTrust;
                        //var certCollection = new X509CertificateCollection();
                        //certCollection.Add(caCert);
                        //certCollection.Add(interCert);
                        //certCollection.Add(cert);

                        //secTrust.SetAnchorCertificates(certCollection);
                        //var credential = new NSUrlCredential(secTrust);
                        var identity = SecIdentity.Import(clientCert);
                        var credential = new NSUrlCredential(identity, new SecCertificate[] { caCert, interCert }, NSUrlCredentialPersistence.ForSession);

                        completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);

                        return;
                    }

我想也许您应该使用NSUrlSessionDelegate进行一些工作。请参阅。在您的链接中,用户没有使用客户端身份验证,而只是使用自签名证书。这已经适用于我发布的NSUrlSessionDelegate实现。我的问题是,这仅在服务器同时请求客户端证书时才起作用te进行身份验证。也许能帮上忙。