C #: как вызвать службу SOAP, требующую аутентификации на стороне клиента, с сертификатами, установленными во время выполнения - PullRequest
8 голосов
/ 15 мая 2019

У меня есть приложение, развернутое в IIS, которое должно вызвать службу SOAP.Он использует WCF из .NET Framework.Эта служба SOAP требует, чтобы сделанные запросы были аутентифицированы с помощью сертификата на стороне клиента, который выдается во время выполнения.Администратор приложения может обновить использованный сертификат в бэк-офисе.Цель состоит в том, чтобы автономия и управление жизненным циклом сертификата были независимыми от IIS или базовой системы, поэтому использование хранилища сертификатов компьютера не является вариантом.Вот исходный код:

var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
var client = new ServiceReference1.myClient(binding, new EndpointAddress(serviceUrl));
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var certificate = new X509Certificate2(certificateBinary, certificatePassword);
client.ClientCredentials.ClientCertificate.Certificate = certificate;

//use the client
var result = client.myMethod(new ServiceReference1.MethodRequest());

certificateBinary является результатом загрузки файла PFX, содержащего полную цепочку сертификатов (клиентский сертификат, промежуточный и корневой CA) и certificatePassword пароль, используемый для создания этого файла,Но запрос отклонен сервером.При взгляде на Wireshark кажется, что отправляется только клиентский сертификат.Это отличается от того, что происходит, если мы устанавливаем PFX в хранилище компьютеров, которое работает нормально.

Поэтому следующим шагом, который я попытался, была установка сертификатов во время выполнения.Сначала загрузите их:

X509Certificate2Collection collection = new X509Certificate2Collection();
try {
    collection.Import(ssCertificateFile, ssPassword, X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet);
}

Затем определите, какие это сертификаты, и, наконец, установите их в текущем хранилище пользователей:

private static void InstallCertificates(X509Certificate2Collection clientCerts, X509Certificate2Collection intermediateCAs, X509Certificate2Collection RootCAs) {
    using (X509Store personalStore = new X509Store(StoreName.My, StoreLocation.CurrentUser)) {
        personalStore.Open(OpenFlags.ReadWrite);
        personalStore.AddRange(clientCerts);
    }

    using (X509Store intermediateStore = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser)) {
        intermediateStore.Open(OpenFlags.ReadWrite);
        intermediateStore.AddRange(intermediateCAs);
    }

    using (X509Store trustedCAsStore = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) {
        trustedCAsStore.Open(OpenFlags.ReadWrite);
        trustedCAsStore.AddRange(rootCAs);
    }
}

Сбой при установке корневых ЦС в доверенный кореньцентры сертификации (StoreName.Root) с:

System.Security.Cryptography.CryptographicException: The request is not supported.
   at System.Security.Cryptography.X509Certificates.X509Store.Add(X509Certificate2 certificate)
   at System.Security.Cryptography.X509Certificates.X509Store.AddRange(X509Certificate2Collection certificates)
   at OutSystems.NssCertificationExtremeXP.CssCertificationExtremeXP.InstallCertificates(CertificatesClassifier certificates)

, поэтому устанавливаются только сертификат клиента и промежуточные центры сертификации, и, по-видимому, во время выполнения этого недостаточно.

Но если я возьму точноетот же самый код и запустить его в отдельном проекте C #, при установке корневых CA появляется диалоговое окно подтверждения , и если я нажимаю OK, сертификат устанавливается.

From здесь и здесь похоже, что каждый раз, когда мы хотим установить что-либо в пользовательских доверенных корневых центрах сертификации, возникает такая подсказка, и , вероятно, не поддерживается в контекстеиспользование не-GUI.

Проблема в том, что даже если я не установлю корневой ЦС в хранилище, я смогу успешно вызвать службу SOAP при запускеg это автономное приложение, только при запуске под IIS это не получается.

Кто-нибудь знает, почему это происходит и как его решить?

...