在Windows平台上,我必须向服务器(服务器A)发送安全消息(双面安全性)。片刻之后,其他一些过程(客户端B)将向我发送第一条消息的处理结果,并且也是双面安全的。
我知道,描述相当长,但是我认为,如果这个问题收到正确的答案,那么我的许多必须发送和接收安全消息的人都可以使用它。
为了确认我的身份,我从当局那里收到了一份证书,仅供我使用,并已被授权:
服务器A使用由证书颁发机构颁发的证书来标识自己
所有文件均为PEM格式。
我已使用MMC.Exe-证书将所有CA证书导入Windows密钥库的本地计算机部分。 MyCertificate.Crt
未导入。
系统提供了Ping / Pong机制:如果我向服务器A发送(空)Ping消息,则客户端B将向我发送Pong消息。
消息以SOAP格式完成
创建并填充WebRequest:
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是一个空(非null)字符串。恕我直言,这意味着PING已正确发送。
在发送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
}
尽管服务器A似乎接受了Ping(我收到了一个空的非空响应),但侦听器似乎从未收到回复。
我知道客户端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, ...)
}