C#/ IRS ACA – 使用WCF 4.5发送包含MTOM附件和GZip编码的Web服务请求

我们正试图通过用于ACA数据传输的公开Web服务向IRS发送数据,并且由于安全标头中的时间戳和签名元素的顺序,我们无法使WSE 3.0方法起作用。 当TimeStamp元素出现在Signature元素之前时,IRS侧的XSDvalidation显示错误。 当我们使用策略断言手动生成具有正确的Signature和Timestamp元素顺序的安全头时,IRS Web服务显示“无效的WS安全头”错误。

任何人都有同样的问题,请告诉我们什么是可能的解决方案。 使用WCF 4.5而不是WSE 3.0是解决方案,请您提供一个使用WCF 4.5处理MTOM附件和GZip编码的工作示例

任何帮助将不胜感激。

编辑:以下是我们现在发送的状态请求肥皂信封,其中包含手动创建的整个XML。 它仍然显示TPE – 1122无效的安全标头错误。 这个要求有什么错误吗?

               [Digest_Value_Replaced]         [Digest_Value_Replaced]         [Digest_Value_Replaced]   [Signature_Value_Replaced]   [Cert_Value_Replaced]     2016-03-23T09:53:23:55Z 2016-03-23T10:03:23:55Z    uuid:SYS12:tcc_cd::T 2016-03-23T09:53:23:55Z   RequestSubmissionStatusDetail     [ReceiptId_Value_Replaced]     

编辑2 ::这是我用来签名信封并创建签名元素的方法。 仍然获得安全头错误…… 🙁

  public static string getSignedXML(XmlDocument xmlDoc, RSACryptoServiceProvider key, string signatureNamespacePrefix, string sTimeStampId, string sManifestId, string sBusHeaderId) { xmlDoc.PreserveWhitespace = false; //Ignore the whitespace in XML SignedXml signedXml = new CustomIdSignedXml(xmlDoc); //If Id attribute needs to have a prefix. This is not needed as per latest Reference Guide Info. //SignedXml signedXml = new SignedXml(xmlDoc); // Add the key to the SignedXml document. signedXml.SigningKey = key; signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url; signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NWithCommentsTransformUrl; signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url; signedXml.Signature.Id = "SIG-E68EBBF1696C5DD4AA143353323390579"; //------------------------------------------------------------------------ //START OF: Adding Manifest, BusinessHeader and TimeStamp References //------------------------------------------------------------------------ //Adding Timestamp Reference XmlDsigExcC14NTransform timeStampTransform = new XmlDsigExcC14NTransform(); timeStampTransform.InclusiveNamespacesPrefixList = "wsse wsa oas1 soapenv urn urn1 urn2 urn3"; Reference reference = new Reference("#" + sTimeStampId); reference.AddTransform(timeStampTransform); // Add the reference to the SignedXml object. signedXml.AddReference(reference); //Adding Business Header Reference XmlDsigExcC14NTransform busHeaderTransform = new XmlDsigExcC14NTransform(); busHeaderTransform.InclusiveNamespacesPrefixList = "wsa oas1 soapenv urn1 urn2 urn3"; reference = new Reference("#" + sBusHeaderId); reference.AddTransform(busHeaderTransform); // Add the reference to the SignedXml object. signedXml.AddReference(reference); //Adding Manifest Request Dtl Reference XmlDsigExcC14NTransform manifestTransform = new XmlDsigExcC14NTransform(); manifestTransform.InclusiveNamespacesPrefixList = "oas1 soapenv urn1 urn2 urn3"; reference = new Reference("#" + sManifestId); reference.AddTransform(manifestTransform); // Add the reference to the SignedXml object. signedXml.AddReference(reference); //------------------------------------------------------------------------ //END OF: Adding Manifest, BusinessHeader and TimeStamp References //------------------------------------------------------------------------ signedXml.ComputeSignature(); XmlElement xmlSignature = signedXml.GetXml(); //Get the singed XML block if (!string.IsNullOrEmpty(signatureNamespacePrefix)) { //Here we set the namespace prefix on the signature element and all child elements to "ds", invalidating the signature. AssignNameSpacePrefixToElementTree(xmlSignature, "ds"); //So let's recompute the SignatureValue based on our new SignatureInfo... //For XPath XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlDoc.NameTable); namespaceManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); //this prefix is arbitrary and used only for XPath XmlElement xmlSignedInfo = xmlSignature.SelectSingleNode("ds:SignedInfo", namespaceManager) as XmlElement; //Canonicalize the SignedInfo element XmlDsigC14NTransform transform = new XmlDsigC14NTransform(); XmlDocument signedInfoDoc = new XmlDocument(); signedInfoDoc.LoadXml(xmlSignedInfo.OuterXml); transform.LoadInput(signedInfoDoc); //Compute the new SignatureValue string signatureValue = Convert.ToBase64String(key.SignData(transform.GetOutput() as MemoryStream, new SHA1CryptoServiceProvider())); //Set it in the xml XmlElement xmlSignatureValue = xmlSignature.SelectSingleNode("ds:SignatureValue", namespaceManager) as XmlElement; xmlSignatureValue.InnerText = signatureValue; } //xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlSignature, true)); //---------------------------------------------------------------------------------- //START OF: Add Key Info Element also to the XML after SignatureValue Node. //---------------------------------------------------------------------------------- X509Certificate2 mycert = new X509Certificate2(, ); //bulkReqTransmitService.ClientCertificates.Add(mycert); var exported = mycert.Export(X509ContentType.Cert, ); var base64 = Convert.ToBase64String(exported); StringBuilder sbKeyInfo = new StringBuilder(); string dsStartTagPrefix = ""; string dsEndTagPrefix = "/"; if (!string.IsNullOrEmpty(signatureNamespacePrefix)) { dsStartTagPrefix = "ds:"; dsEndTagPrefix = "/ds:"; } sbKeyInfo.Append(""); sbKeyInfo.Append(""); sbKeyInfo.Append(""); sbKeyInfo.Append("" + base64.ToString()); sbKeyInfo.Append(""); sbKeyInfo.Append(""); sbKeyInfo.Append(""); sbKeyInfo.Append(""); XmlDocument tempDoc = new XmlDocument(); tempDoc.LoadXml(sbKeyInfo.ToString()); XmlNode oNode = tempDoc.DocumentElement; //necessary for crossing XmlDocument contexts XmlNode importNode = xmlSignature.OwnerDocument.ImportNode(oNode.FirstChild, true); xmlSignature.AppendChild(importNode); //---------------------------------------------------------------------------------- //END OF: Add Key Info Element also to the XML after SignatureValue Node. //---------------------------------------------------------------------------------- return xmlSignature.OuterXml; } public class CustomIdSignedXml : SignedXml { public CustomIdSignedXml(XmlDocument xml) : base(xml) { } public CustomIdSignedXml(XmlElement xmlElement) : base(xmlElement) { } public override XmlElement GetIdElement(XmlDocument doc, string id) { // check to see if it's a standard ID reference XmlElement idElem = base.GetIdElement(doc, id); if (idElem == null) { XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable); nsManager.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); //idElem = doc.SelectSingleNode("//*[@p5:Id=\"" + id + "\"]", nsManager) as XmlElement; string xml = doc.SelectSingleNode("//*[@wsu:Id=\"" + id + "\"]", nsManager).OuterXml; XmlDocument tempDoc = new XmlDocument(); tempDoc.LoadXml(xml); XmlElement xEle = tempDoc.DocumentElement; idElem = xEle; } return idElem; } } 

编辑 :validation由于WCF的消息传递架构,这一切都不会起作用。 IRS结构要求修改HTTP头以使MTOM正常工作,在发生XML序列化之后,无法在WCF中修改。 您必须手动构建XML并通过HttpClient发送它并自己进行GZip和MTOM编码。 关于这些坏消息我很遗憾 :(

WCF gzip:在此处获取示例,并将类和客户端配置与您的应用程序集成。 https://msdn.microsoft.com/en-us/library/ms751458.aspx

您必须将内容类型调整为“text / xml”而不是“application / x-gzip”。

这仍然会被IRS拒绝,因为这不会设置“Content-Encoding”标头。 您可以这样设置内容编码:

使用(new OperationContextScope(transmitterClient.InnerChannel))
{
//将HTTP标头添加到传出请求
HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
requestMessage.Headers [“Content-Encoding”] =“gzip”;
OperationContext.Current.OutgoingMessageProperties [HttpRequestMessageProperty.Name] = requestMessage;
return port.BulkRequestTransmitter(request);
}

感谢这篇博客文章: http : //blogs.msdn.com/b/wsdevsol/archive/2014/02/07/adding-custom-messageheader-and-http-header-to-a-wcf-method- call.aspx

此外,IRS的响应不是gzip压缩,因此您需要修改类以不尝试解压缩响应。

此外,另外,innerMessageEncoding messageVersion默认与IRS不兼容。 您必须修改GZipMessageEncodingElement的ApplyConfiguration方法,以使用Encoding.UTF8将TextMessageEncodingBindingElement实例化为MessageVersion.Soap11WSAddressing10枚举。

MTOM我的绑定看起来像这样:

          

然后是针对我的证书的自定义行为。

我还没有在你的post上发表评论的声誉> 🙁

以下是您关于所使用流程的几个后续问题。

  1. 您是否使用WSDL服务参考/代理类通过ISS-A2A频道拨打IRS?
  2. 从示例中实现三个类文件后,我收到以下错误。 你看到我做错了什么吗?

附加信息:无法加载为扩展名’gzipMessageEncoding’注册的类型'[Project] .GZipEncoder.GzipMessageEncodingElement,GZipEncoder,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null’。

我的元素给了我一个警告,我认为这与上面的错误有关。

的app.config