На платформе Windows я должен отправить защищенное сообщение (двусторонняя защита) на сервер (Сервер A).Через несколько мгновений какой-то другой процесс (Клиент B) отправит мне обработанные результаты первого сообщения, также двухсторонней защиты.
Я знаю, описание довольно длинное, но я думаю, что если этот вопрос получитПравильный ответ, он может быть использован многими, кто должен отправлять и получать защищенные сообщения.
Безопасность
- Для сообщения на сервер я использую HttpWebRequest
- Чтобы получить ответ, я использую HttpListener.
Чтобы идентифицировать меня, я получил от органов власти только сертификат, который будет использоваться мной, который разрешен:
- Root CA-G3
- Промежуточный CA-G3
- MyCertificate.CRT и MyCertificate.Private.Key
Сервер A идентифицирует себя, используя сертификат, выданныйцентры сертификации
- Root CA-G2
- Промежуточный CA-G2
Все файлы в формате PEM.
Я импортировалвсе сертификаты CA на локальный компьютериз хранилища ключей Windows, используя MMC.Exe - Сертификаты.MyCertificate.Crt
не импортируется.
В системе предусмотрен механизм Ping / Pong: если я отправлю (пустое) сообщение Ping на сервер A, клиент B отправит мне сообщение Pong.
Обмен сообщениями осуществляется в формате SOAP
Отправка PING
Создание и заполнение веб-запроса:
const string requestUriString = "https://...nl:443/deliver";
HttpWebRequest webRequest = WebRequest.CreateHttp(requestUriString);
webRequest.Headers.Add(@"SOAP:Action");
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
// Create the Soap Envelope
string soapEnvelopeXmlText = CreateOutXmlMessage(); // see below
XmlDocument soapEnvelopeDocument = new XmlDocument();
soapEnvelopeDocument.LoadXml(soapEnvelopeXmlText);
// Fill the webRequest with the soap envelope:
using (System.IO.Stream stream = webRequest.GetRequestStream())
{
soapEnvelope.Save(stream);
}
// Add Security to the webRequest
string certificateFile = Path.Combine(certificateFolder, "MyCertificate.Crt");
X509Cerficiate certificate = X509Certificate.CreateFromCertFlie(certificateFile);
Отправьте запрос, дождитесь ответа и интерпретируйте его:
using (WebResponse response = webRequest.GetResponse())
{
// interpret the response:
using (var reader = new StreamReader(response.GetResponseStream()))
{
string responseText= reader.ReadToEnd();
this.Process(responseText);
}
}
responseText - пустая (ненулевая) строка.IMHO, это означает, что PING был отправлен правильно.
Получение PONG
Перед отправкой Ping необходимо запустить HttpListener
.
Я ожидаюответы должны быть получены через порт 443, через порт 443. Клиент отправит его, используя адрес типа https:mycompany.com:443/reply
using (HttpListener httpListener = new HttpListener())
{
httpListener.Prefixes.Add(@"https://*:443/reply");
httpListener.Start();
// start listening on a separate task.
// this enables proper stopping:
Task.Factory.StartNew(async () =>
{
while (true) await ListenAsync(httpListener);
},
TaskCreationOptions.LongRunning);
}
async Task ListenAsync(HttpListener httpListener)
{
// Listen by getting the context:
HttpListenerContext context = await this.httpListener.GetContextAsync();
// Problem: the code never comes to this point
... interpret context
}
Проблемы
Хотя кажется, что Ping принят серверомA (я получаю пустой ненулевой ответ), кажется, что ответ никогда не получен слушателем.
Я знаю, что клиент B пытается отправить мне ответ, потому что если я использую вместо этого Apache Tomcatчтобы прослушать, я получаю сообщение журнала о том, что что-то получено через порт 443. Хотя я не вижу содержимого этого сообщения, я знаю, что оно правильно расшифровано, поскольку в сообщении журнала понимается тип ответа (ebXML).
Наконец, не важно для вопроса, но если вы действительно хотите знать: содержание SOAP xml:
private string CreateOutXmlMessage()
{
const string formatStr = @"<?xml version=""1.0"" encoding=""utf-8""?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/""
xmlns:eb=""http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd""
xmlns:xlink=""http://www.w3.org/1999/xlink""
xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xsi:schemaLocation=""http://schemas.xmlsoap.org/soap/envelope/ http://www.oasis-open.org/committees/ebxml-msg/schema/envelope.xsd"">
<SOAP-ENV:Header xsi:schemaLocation=""http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd"">
<eb:MessageHeader SOAP-ENV:mustUnderstand=""1"" eb:version=""2.0"">
<eb:From>
<eb:PartyId eb:type=""{0}"">{1}</eb:PartyId>
<eb:Role>{2}</eb:Role>
</eb:From>
<eb:To>
<eb:PartyId eb:type=""{3}"">{4}</eb:PartyId>
<eb:Role>{5}</eb:Role>
</eb:To>
<eb:CPAId>{6}</eb:CPAId>
<eb:ConversationId>{7}</eb:ConversationId>
<eb:Service>urn:oasis:names:tc:ebxml-msg:service</eb:Service>
<eb:Action>{8}</eb:Action>
<eb:MessageData>
<eb:MessageId>{9}</eb:MessageId>
<eb:Timestamp>{10:O}</eb:Timestamp>
</eb:MessageData>
</eb:MessageHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<eb:Manifest eb:id=""Manifest"" eb:version=""2.0""/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>";
return String.Format(formatStr, ...)
}