C#学习教程:使用X.509证书从WCF服务签署SOAP消息到JavaWeb服务希望这是有道理的。我在网上看到了几个与此问题相关的博客,并且尝试了一些想法但没有成功。这是我的情况:我有一个Web应用程序调用WCFWeb服务,然后调用JavaWeb服务。他们都在不同的服务器上。WCFWeb服务和JavaWeb服务之间的调用不会通过https,因为证书足以识别调用者(因此消息安全)。JavaWeb服务需要接收签名消息并按如下方式工作:在处理每个请求之前,处理程序拦截所有传入消息并强制执行以下验证规则:1.消息是否包含安全标头2.消息是否包含正确的安全性标头ID3.消息是否正确签名4.消息是否包含KeyInfox.509证书5.证书是否来自受信任的CA-配置6.证书是否有效(未过期,已吊销)7.证书是否包含正确的policyOID确认完所有这些步骤后,就可以处理消息了,如果任何一步失败,将返回soap消息异常。SOAP安全标头应根据xxx...w3.org/TR/SOAP-dsig/数字签名规范进行身份验证。可以在此处找到最完整的描述xxx...ibm.com/developerworks/webservices/library/ws-security.html这篇IBM文章列出了每个WS-Security标头的详细信息,并另外提供了一个示例签名SOAP消息。签署SOAP消息时,还必须将x.509证书添加到消息KeyInfo中,这是证书验证所必需的。SOAP请求应该是这样的:soe1PnaGXVGrsauC61JSHD+uqGw=Y9SRPQ9TcDu+GazO3LFwodEdhaA=jBX/8XkY2aCte7qgXEp1sbNWmQcK/90iVL58sAvwYAEcBABGzOk2agxR0HvWrNa6ixkocAQ205lggwOxnxZJvoVozVYAAjcLtayPBOUYrnSEBFrwKWP/vxgvUDRIdXeIuw5GLY87NrTQMm1Ehf/HvMX9hTBJn4Nm8RdDiUmPcIo=MIIEbZCCA1WgAwIBAgIES1XpMjANBgkqhkiG9w0BAQUFADBYMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFzAVBgoJkiaJk/IsZAEZFgdlbnRydXN0MRIwEAYDVQQDEwllbnRydXN0U00xEjAQBgNVBAMTCWVudHJ1c3RDQTAeFw0xMDA0MjIxMDQ4MDBaFw0xMzA0MjIxMTE4MDBaMGoxFTATBgoJkiaJk/IsZAEZFgVsb2NhbDEXMBUGCgmSJomT8ixkARkWB2VudHJ1c3QxEjAQBgNVBAMTCWVudHJ1c3RTTTESMBAGA1UEAxMJZW50cnVzdENBMRAwDgYDVQQDEwdSYnMgUmJzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMf88L2JjLPG1hNmTA/KBiC53WVwS2WU9Jh3lC1Rob6RMzOojomZ/dNrvSRB6nzWeXJpZXwik4XFrsAq24By2SZpLTO4p8Vcq71mTAfDu33cnO49Au2pwNvcMn5qIKBk1Xx+oVb4fzK9ncTRu7bW46HsIYth+qkGhbI2JEHwr/zwIDAQABo4IBrzCCAaswCwYDVR0PBAQDAgeAMCsGA1UdEAQkMCKADzIwMTAwNDIyMTA0ODAwWoEPMjAxMjA1MjgxNTE4MDBaMCMGA1UdIAQcMBowCwYJYIZIAYb6awoEMAsGCSqGSIb2fQdLAzAbBgNVHQkEFDASMBAGCSqGSIb2fQdEHTEDAgEBMIHGBgNVHR8Egb4wgbswb6BtoGukaTBnMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFzAVBgoJkiaJk/IsZAEZFgdlbnRydXN0MRIwEAYDVQQDEwllbnRydXN0U00xEjAQBgNVBAMTCWVudHJ1c3RDQTENMAsGA1UEAxMEQ1JMMTBIoEagRIZCZmlsZTovLy8vTVNJREhVLTQ0NUE0RkVFL0NSTC9lbnRydXN0Y2FfZW50cnVzdHNtX2xvY2FsX2NybGZpbGUuY3JsMB8GA1UdIwQYMBaAFBvSL6cPz8L5shubV58yf0pczKzuMB0GA1UdDgQWBBT1/j6OSS8FTjwqluvew16sv7h+VzAJBgNVHRMEAjAAMBkGCSqGSIb2fQdBAAQMMAobBFY4LjADAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQBXxRIA4HUvGSw4L+4uaR51pY4ISjUQWo2Fh7FYBMt29NsKCTdur1OWVVdndt1yjXP4yWXxoAhHtvZL+XNALUFlR2HAWiXuL1nRcxHkB98N5gPqQzW/lJk9cLtL4hVp28EiEpgmKT3I3NP2Pdb2G5MMOdvQ/GFb2y6OwblR8ViPQ8B2aHWzXMrH+0qadPAuBhXyAohwb+mMuYT/ms6xpGi1NMYuYMf6XONz9GkZgnGnMwa+9CCQws1HNz8WYHtmFIxLsVuEWc/0a1vg4IYX1Ds/ttyhJGTVXOSJSkBz8kRyj1pNBDdc1KeG8M++O8m8VgRTJvYaPc7NMiclISukGpea0061020051我有一个服务器证书(来自可靠CA的p7b格式),我安装在我的WCFWebServiceWorkstation(dev)usesmmcCertificateSnap-in(currentlycertisintrustedpublishers)我不认为我需要在Java服务器上使用另一个证书,因为响应应该是明确的(既没有签名也没有加密)。我仍然对这个证书有点困惑——一般来说是证书——因为它似乎只持有一个公钥。这是我的测试项目的app.config:当我运行一个简单的测试时:WebASentrustService=newWebAS();ActivationCodescertCodes=entrustService.createUser("testNomad");我有错误:失败:System.Web.Services.Protocols.SoapException:javax.xml.soap.SOAPException:在soap消息中找不到签名元素如何强制对每条消息进行签名过程?我以为我可以使用WCF配置轻松完成。任何帮助将不胜感激!好的。经过几次试验和错误后,这是一个使用SignedXml和IClientMessageInspector/BeforeSendRequest模式的解决方案。非常感谢YaronNaveh的相关建议。//签署一个XML请求并返回它如果(string.IsNullOrEmpty(SubjectName))抛出新的ArgumentNullException("SubjectName");//从证书库加载证书。X509Certificate2cert=GetCertificateBySubject(SubjectName);//创建一个新的XML文档。XmlDocumentdoc=newXmlDocument();//格式化文档以忽略空格。doc.PreserveWhitespace=false;//加载传入的XMLdoc.LoadXml(request);//根据提供的Entrust示例添加声明-不要认为这是必要的if(!(doc.FirstChildisXmlDeclaration)){XmlDeclarationdeclaration=doc.CreateXmlDeclaration("1.0","UTF-8",string.Empty);doc.InsertBefore(声明,doc.FirstChild);}//移除动作(MustUnderstand)。//TODO:需要找到一个更优雅的这样做的方法XmlNodeheaderNode=null;XmlNodeListnodeList=doc.GetElementsByTagName("Action");如果(nodeList.Count>0){headerNode=nodeList[0].ParentNode;headerNode.RemoveChild(nodeList[0]);}//设置bodyid-未使用但在该项目的后期可能有用XmlNamespaceManagerns=newXmlNamespaceManager(doc.NameTable);ns.AddNamespace("s","http://schemas.xmlsoap.org/soap/envelope/");XmlElementbody=doc.DocumentElement.SelectSingleNode(@"//s:Body",ns)asXmlElement;if(body==null)thrownewApplicationException("Nobodytagfound");body.RemoveAllAttributes();//不需要命名空间body.SetAttribute("Id","ABC");//BodyId可以作为参数传递//创建一个自定义SignedXml对象,以便我们可以对密钥信息进行签名CustomSignedXmlsignedXml=newCustomSignedXml(doc);//将密钥添加到SignedXml文档。signedXml.SigningKey=cert.PrivateKey;//创建一个新的KeyInfo对象。KeyInfo键信息=新的关键信息();keyInfo.Id=keyInfoRefId;//将证书加载到KeyInfoX509Data对象中//并将其添加到KeyInfo对象中。KeyInfoX509DatakeyInfoData=newKeyInfoX509Data();keyInfoData.AddCertificate(cert);keyInfo.AddClause(keyInfoData);//将KeyInfo对象添加到SignedXml对象。signedXml.KeyInfo=keyInfo;//创建要签名的引用。引用reference=newReference();参考.Uri="";//向引用添加一个封装转换。XmlDsigEnvelopedSignatureTransformenv=newXmlDsigEnvelopedSignatureTransform();reference.AddTransform(env);//添加对SignedXml对象的引用。signedXml.AddReference(参考);引用reference2=newReference();reference2.Uri="#"+keyInfoRefId;signedXml.AddReference(reference2);//添加签名IdsignedXml.Signature.Id=Signature;//计算签名。signedXml.ComputeSignature();//获取签名的XML表示并保存//它到一个XmlElement对象。XmlElementxmlDigitalSignature=signedXml.GetXml();//将Signature元素附加到XML文档。if(headerNode!=null){headerNode.AppendChild(doc.ImportNode(xmlDigitalSignature,true));}返回doc.InnerXml;}publicstaticX509Certificate2GetCertificateBySubject(stringCertificateSubject){//检查参数。如果(string.IsNullOrEmpty(CertificateSubject))抛出新的ArgumentNullException("CertificateSubject");//从证书库加载证书。X509Certificate2证书=空;X509Storestore=newX509Store(StoreName.My,StoreLocation.CurrentUser);try{//打开商店。store.Open(OpenFlags.ReadOnly|OpenFlags.OpenExistingOnly);//查找具有指定主题的证书。cert=store.Certificates.Find(X509FindType.FindBySubjectName,CertificateSubject,false)[0];//抛出证书未找到的异常。if(cert==null){thrownewCryptographicException("The找不到证书。");}}finally{//即使抛出异常也关闭商店。store.Close();}returncert;}和CustomSignedXml类:publicclassCustomSignedXml:SignedXml{publicCustomSignedXml(XmlDocumentdoc):base(doc){return;}publicoverrideXmlElementGetIdElement(XmlDocumentdoc,stringid){//查看这是否是被引用的关键信息,否则返回默认行为if(String.Compare(id,this.KeyInfo.Id,StringComparison.OrdinalIgnoreCase)==0)returnthis.KeyInfo.GetXml();elsereturnbase.GetIdElement(doc,id);}}你能捕获WCF服务发送的消息吗?WSDL由中描述的Java服务使用的消息安全方式-这将使事情变得更容易。根据你的描述,我认为你的配置是错误的,因为在使用证书客户端凭据时,你需要两个证书-带有公钥和私钥的客户端证书和带有公钥的服务器证书。它也可能在您的要求中描述:消息是否包含KeyInfox.509证书是从受信任的CA颁发的证书-基于配置为什么需要它发送已安装在该服务器上的服务证书服务器?为什么该服务会检查其证书是否来自受信任的CA?我想这些要求表明您必须为您的客户创建新证书。但这些只是假设,因为实际需求通常用共享语言描述-WSDL+WS-Security断言。签名和加密可以在多个级别上进行控制。首先,每个ServiceContract和MessageContract都有ProtectionLevel属性,默认为EncryptAndSign。您可以将其更改为签名。以上就是C#学习教程:使用X.509证书从WCF服务到JavaWebservice对SOAP消息进行签名,分享全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多加关注——本文整理自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
