我試圖使用WCF客戶端連接到 WCF:該EncryptedKey條款不包裹所需的加密令牌「System.IdentityModel.Tokens.X509SecurityToken」
證書我已經提供了基於Java的Web服務
(自簽名)在SOAPUI中完美工作。這裏是我的設置:
不過,我在使用WCF客戶端時遇到問題。
我的app.config
<bindings>
<customBinding>
<binding name="Example_TestBinding">
<security defaultAlgorithmSuite="TripleDesRsa15"
authenticationMode="MutualCertificate"
requireDerivedKeys="false"
includeTimestamp="false"
messageProtectionOrder="SignBeforeEncrypt"
messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"
requireSignatureConfirmation="false">
<localClientSettings detectReplays="true"/>
<localServiceSettings detectReplays="true"/>
</security>
<textMessageEncoding messageVersion="Soap11"/>
<httpsTransport authenticationScheme="Basic" manualAddressing="false" maxReceivedMessageSize="524288000" transferMode="Buffered"/>
</binding>
</customBinding>
</bindings>
<client>
<endpoint
address="https://blabla.hana.ondemand.com/Example_Test"
binding="customBinding"
bindingConfiguration="Example_TestBinding"
contract="WebServiceTest.Example_Test"
name="Example_Test"
/>
</client>
使用密鑰庫資源管理器中,我從JKS同時導出證書爲:
- public_test_hci_cert.cer
- test_soap_ui.p12
Web服務c所有:
var client = new Example_TestClient();
client.ClientCredentials.UserName.UserName = "user";
client.ClientCredentials.UserName.Password = "pass";
X509Certificate2 certClient = new X509Certificate2(certClientPath, certClientPassword);
client.ClientCredentials.ClientCertificate.Certificate = certClient;
X509Certificate2 certService= new X509Certificate2(certServicePath);
client.ClientCredentials.ServiceCertificate.DefaultCertificate = certService;
var response = client.Example_Test(requestObj);
請求完全到達服務器,但它似乎WCF不理解響應,因爲我得到這個異常:
"The EncryptedKey clause was not wrapped with the required
encryption token 'System.IdentityModel.Tokens.X509SecurityToken'."
at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.CreateWrappedKeyToken(String id, String encryptionMethod, String carriedKeyName, SecurityKeyIdentifier unwrappingTokenIdentifier, Byte[] wrappedKey, SecurityTokenResolver tokenResolver)\r\n ...
服務跟蹤,得出:
The security protocol cannot verify the incoming message
UPDATE1:通過使用相同的證書進行簽名和加密來簡化任務。同樣的信息。
UPDATE2:我寫了CustomTextMessageEncoder,我手動解密郵件正文,它的工作原理。但是,在ReadMessage中返回它仍會引發錯誤。
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
var msgContents = new byte[buffer.Count];
Array.Copy(buffer.Array, buffer.Offset, msgContents, 0, msgContents.Length);
bufferManager.ReturnBuffer(buffer.Array);
var message = Encoding.UTF8.GetString(msgContents);
//return ReadMessage(Decryptor.DecryptBody(message), int.MaxValue);
var stream = new MemoryStream(Encoding.UTF8.GetBytes(message));
return ReadMessage(stream, int.MaxValue);
}
public static MemoryStream DecryptBody(string xmlResponse)
{
X509Certificate2 cert = new X509Certificate2(clientCertPath, certPass);
SymmetricAlgorithm algorithm = new TripleDESCryptoServiceProvider();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(xmlResponse);
XmlElement encryptedKeyElement = xmlDoc.GetElementsByTagName("EncryptedKey", XmlEncryptionStrings.Namespace)[0] as XmlElement;
XmlElement keyCipherValueElement = encryptedKeyElement.GetElementsByTagName("CipherValue", XmlEncryptionStrings.Namespace)[0] as XmlElement;
XmlElement encryptedElement = xmlDoc.GetElementsByTagName("EncryptedData", XmlEncryptionStrings.Namespace)[0] as XmlElement;
var key = Convert.FromBase64String(keyCipherValueElement.InnerText);
EncryptedData edElement = new EncryptedData();
edElement.LoadXml(encryptedElement);
EncryptedXml exml = new EncryptedXml();
algorithm.Key = (cert.PrivateKey as RSACryptoServiceProvider).Decrypt(key, false);
byte[] rgbOutput = exml.DecryptData(edElement, algorithm);
exml.ReplaceData(encryptedElement, rgbOutput);
//var body = Encoding.UTF8.GetString(rgbOutput);
MemoryStream ms = new MemoryStream();
xmlDoc.Save(ms);
return ms;
}
它確實:證書是錯誤的。你還想知道什麼? –