Доброго времени суток!
Имеется удаленный сервис на Apache Axis (находится в домене А) запросы к которому необходимо подписывать с помощью сертификата. Необходимо написать клиента на C# (находится в домене Б и никак не связан с доменом А) который бы отправлял данный запрос от имени пользователя домена А, сертификат которого выгружен в *.P12 (с приватным ключом). Полученный сертификат прогрузил в хранилище винды и оттуда его беру.
По мануалу к сервису можно обратится
1) через HTTP - подписать сам SOAP запрос (в секции header),
2) через транспортный уровень HTTPS.
В обоих случаях получаю ответ от сервиса - (403)Forbidden. Причем ошибка явно на уровне первичной аутентификации, т.к. согласно мануалу отсутствие прав на выполнение имеет другой формат ошибки.
Люди, кто поддерживают сервис на домене А говорят что ssl handshake вроде проходит, но пользователь не определяется. Эти люди мне сертификат и давали.
Подскажите плз, в каком мне направлении копать? может какие то махинации с сертификатом надо произвести?
Вариант 1. Пример запроса через HTTP (SignXML):
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#Body">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>6kkrzRtR.....</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>V2Wod0G.............</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIICxTCCAa2gAw.................</ds:X509Certificate>
</ds:X509Data>
<ds:KeyValue>
<ds:RSAKeyValue>
<ds:Modulus>1k6698yXPa9b..........</ds:Modulus>
<ds:Exponent>AQAB</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</ds:Signature>
</soapenv:Header>
<soapenv:Body Id="Body">
...
</soapenv:Body>
</soapenv:Envelope>
Соответствующий код C#:
public string postXMLData(string destinationUrl, XElement operationXml, string certName)
{
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
var xml = XmlSecurity.GenerateSoapXml(operationXml);
var signXml = XmlSecurity.SignRequest(xml, certName);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(destinationUrl);
request.Headers.Add("SOAPAction: \"\"");
request.ContentType = "text/xml; charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";
try
{
using (var requestStream = request.GetRequestStream())
{
signXml.Save(requestStream);
}
var response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
using (Stream responseStream = response.GetResponseStream())
{
return new StreamReader(responseStream).ReadToEnd();
}
}
}
catch (Exception ex)
{
return ex.ToString();
}
return null;
}
Вариант 2. А так я пытался отправить через HTTPS:
public string postXMLData(string destinationUrl, XElement operationXml, string certName)
{
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
var xml = XmlSecurity.GenerateSoapXml(operationXml);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(destinationUrl);
request.Headers.Add("SOAPAction: \"\"");
request.ContentType = "text/xml; charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";
request.Credentials = new NetworkCredential("Login", "Pass", "Domain");
request.ClientCertificates.Add(XmlSecurity.GetCertificateBySubject(certName));
try
{
using (var requestStream = request.GetRequestStream())
{
xml.Save(requestStream);
}
var response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
using (Stream responseStream = response.GetResponseStream())
{
return new StreamReader(responseStream).ReadToEnd();
}
}
}
catch (Exception ex)
{
return ex.ToString();
}
return null;
}