对我来说是新的:我需要使用提供商颁发的证书对来自 ColdFusion 客户端应用程序的 SOAP 请求的主体进行数字签名和加密。我还需要解密响应以进行处理。
我已经搜索了几天,一无所获。我找到了引用其他语言的信息,但在 ColdFusion 中没有。如果无法通过 ColdFusion 语言 API 本地执行此操作,有人可以帮助我通过“createObject()”函数或您可能拥有的任何其他方法调用正确的 Java 或 .net 类吗?
2012 年 9 月 17 日 - 附加信息:
更多信息:我在查看代码时发布超时。这是完整的帖子:
我正在使用一项 Web 服务,而不是提供一项。我已经达到了让整个工作正常工作的地步,但它只能通过 ColdFusion“createObject”调用工作一次。
仍然需要帮助。系统:带有 ColdFusion 9 单服务器安装的 Windows Server 2003。
我使用了 Apache 的 wss4J 库并编写了一个简单的 Java 类作为入口点。自定义 Java 类只需将完整的 SOAP 消息作为 String 参数,将 String 传递给 wss4j DateStamp 类,然后将生成的 SOAP 部分对象传递给签名类,然后是加密类。然后它返回签名和加密的 SOAP 信封,该信封已通过 PrettyDocumentToString 函数从文档(SOAP 部分)转换为字符串。
所有这些都有效,我得到了一个带有安全标头和签名加密正文的 SOAP 信封。问题是,在重新启动 ColdFusion 服务(在 Windows Server 2003 上安装单服务器)后,它一次全部工作,但随后的运行导致 wss4j 签名代码中出现错误。我什至使用 Winmerge 在重新启动后立即比较了整个 ColdFusion9 目录,在第一次运行后立即运行,在第二次运行后立即进行比较。唯一的区别在于日志文件。ColdFusion9\lib\neo-datasource.xml 文件中存在差异,但仅在几个数据源描述符的顺序上,而不是在内容上。
下面是代码和堆栈跟踪:
writeOutputs 和 writeDumps 仅用于调试期间的可视化。
ColdFusion 调用脚本:
<cfscript>
variables.tempPath = getDirectoryFromPath(getCurrentTemplatePath());
variables.filePath = tempPath & "ASI_source_request_example.xml";
variables.fileContent = FileRead(filePath);
writeOutput("FILECONTENT: <br>");
writeOutput("variables.fileContent);
writeDump(var="#variables.fileContent#", format="html", output="#expandPath('./')#_DUMP-OUTPUT.htm");
variables.encSOAP=createobject("java","ProcessIDSRSSOAP").runProcess(fileContent);
writeOutput("<br><br>encSOAP: <br>");
writeOutput(variables.encSOAP);
writeDump(var="#variables.encSOAP#", format="html", output="#expandPath('./')#_DUMP-OUTPUT.htm");
</cfscript>
Java类:
import java.io.FileReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.ws.security.SOAPConstants;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.common.SOAPUtil;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.message.WSSecEncrypt;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecTimestamp;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;
public class ProcessIDSRSSOAP {
private static Crypto crypto = null;
private static Properties properties = new Properties();
private static String user = "";
private static String cryptoPwd = "";
private static WSSecSignature builder = new WSSecSignature();
private static SOAPConstants soapConstants = null;
private final WSSecHeader secHeader = new WSSecHeader();
private Document tsDoc = null;
private Document signedDoc = null;
private Document encryptedDoc = null;
private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
.getLog(ProcessIDSRSSOAP.class);
public ProcessIDSRSSOAP() throws Exception {
WSSConfig.init();
}
/*
* public static void main(String[] args) throws Exception {
* ProcessIDSRSSOAP processor = new ProcessIDSRSSOAP();
* processor.runProcess(args[0]); }
*/
public String runProcess(String inDoc) throws Exception {
// ProcessIDSRSSOAP processor = new ProcessIDSRSSOAP();
// LOG.debug(inDoc);
Class<ProcessIDSRSSOAP> thisClass = ProcessIDSRSSOAP.class;
ClassLoader thisLoader = thisClass.getClassLoader();
URL propertiesURL = thisLoader.getResource("crypto.properties");
String propertiesPath = propertiesURL.getPath();
propertiesPath = propertiesPath.replaceAll("%20", " ");
properties.load(new FileReader(propertiesPath));
user = properties
.getProperty("org.apache.ws.security.crypto.merlin.keystore.alias");
cryptoPwd = properties
.getProperty("org.apache.ws.security.crypto.merlin.keystore.password");
crypto = CryptoFactory.getInstance("crypto.properties");
builder.setUserInfo(user, cryptoPwd);
builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
SOAPUtil.toSOAPPart(inDoc.trim());
Document PKIDoc = processDoc(inDoc);
String PKIDocString = org.apache.ws.security.util.XMLUtils
.PrettyDocumentToString(PKIDoc);
LOG.debug(PKIDocString);
return PKIDocString;
}
/**
* @param SOAPMsg
* The entire SOAP message as a type String
* @throws Exception
*/
public Document processDoc(String SOAPMsg) throws Exception {
tsDoc = timestampMSG(SOAPMsg);// Time stamp the SOAP String and make it
// a Document type.
secHeader.insertSecurityHeader(tsDoc);// Insert the security header.
soapConstants = WSSecurityUtil.getSOAPConstants(tsDoc
.getDocumentElement());
signedDoc = signBody(tsDoc);// Send the Document on for signing.
encryptedDoc = encryptBody(signedDoc);
return encryptedDoc;
}
/**
* @param msg
* The entire SOAP message as a type String
* @throws Exception
*/
public Document timestampMSG(String msg) throws Exception {
Document doc = SOAPUtil.toSOAPPart(msg);
WSSecHeader secHeader = new WSSecHeader();
secHeader.insertSecurityHeader(doc);
WSSecTimestamp timestamp = new WSSecTimestamp();
timestamp.setTimeToLive(300);
Document createdDoc = timestamp.build(doc, secHeader);
return createdDoc;
}
/**
* @param doc
* Expects a SOAP message as a type Document
* @throws Exception
*/
public Document signBody(Document doc) throws Exception {
List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
WSEncryptionPart encP = new WSEncryptionPart(soapConstants
.getBodyQName().getLocalPart(), soapConstants.getEnvelopeURI(),
"");
parts.add(encP);
builder.setParts(parts);
Document signedDoc = builder.build(doc, crypto, secHeader);
return signedDoc;
}
public Document encryptBody(Document doc) throws Exception {
SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
.getDocumentElement());
WSSecEncrypt encrypt = new WSSecEncrypt();
encrypt.setUserInfo(user, cryptoPwd);
encrypt.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
WSSecHeader secHeader = new WSSecHeader();
secHeader.insertSecurityHeader(doc);
List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
WSEncryptionPart encP = new WSEncryptionPart(soapConstants
.getBodyQName().getLocalPart(), // define the body
soapConstants.getEnvelopeURI(), "");
parts.add(encP);
encrypt.setParts(parts);
Document encryptedDoc = encrypt.build(doc, crypto, secHeader);
return encryptedDoc;
}
}
冷融合错误:
Signature creation failed (Cannot setup signature data structure)
The error occurred in G:/Inetpub/wwwroot/SOAP/index.cfm: line 14
12 : writeDump(var="#variables.fileContent#", format="html", output="#expandPath('./')#_DUMP-OUTPUT.htm");
13 :
14 : variables.encSOAP=createobject("java","ProcessIDSRSSOAP").runProcess(fileContent);
15 :
16 : writeOutput("<br><br>encSOAP: <br>");
堆栈跟踪:
at cfindex2ecfm1134068877.runPage(G:/Inetpub/wwwroot/SOAP/index.cfm:14)
org.apache.ws.security.WSSecurityException: Signature creation failed (Cannot setup signature data structure)
at org.apache.ws.security.message.WSSecSignatureBase.addReferencesToSign(WSSecSignatureBase.java:191)
at org.apache.ws.security.message.WSSecSignature.addReferencesToSign(WSSecSignature.java:409)
at org.apache.ws.security.message.WSSecSignature.build(WSSecSignature.java:381)
at ProcessIDSRSSOAP.signBody(ProcessIDSRSSOAP.java:118)
at ProcessIDSRSSOAP.processDoc(ProcessIDSRSSOAP.java:85)
at ProcessIDSRSSOAP.runProcess(ProcessIDSRSSOAP.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at coldfusion.runtime.java.JavaProxy.invoke(JavaProxy.java:97)
at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2360)
at cfindex2ecfm1134068877.runPage(G:\Inetpub\wwwroot\SOAP\index.cfm:14)
at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231)
at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416)
at coldfusion.filter.CfincludeFilter.invoke(CfincludeFilter.java:65)
at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:381)
at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48)
at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)
at coldfusion.filter.PathFilter.invoke(PathFilter.java:94)
at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70)
at coldfusion.filter.BrowserDebugFilter.invoke(BrowserDebugFilter.java:79)
at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)
at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46)
at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62)
at coldfusion.CfmServlet.service(CfmServlet.java:200)
at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)
at jrun.servlet.FilterChain.doFilter(FilterChain.java:86)
at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)
at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)
at jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
at jrun.servlet.FilterChain.service(FilterChain.java:101)
at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)
at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)
at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)
at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)
at jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)
at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
at jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)
at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)
Caused by: java.lang.NullPointerException
at org.apache.ws.security.message.DOMCallbackLookup.getElements(DOMCallbackLookup.java:94)
at org.apache.ws.security.util.WSSecurityUtil.findElements(WSSecurityUtil.java:267)
at org.apache.ws.security.message.WSSecSignatureBase.addReferencesToSign(WSSecSignatureBase.java:156)
... 43 more
显然,org.apache.ws.security.message.DOMCallbackLookup.getElements 中缺少某些内容。提供它的代码是:
return callbackLookup.getElements(part.getName(),part.getNamespace());
我似乎无法弄清楚为什么它在从 CF 调用时第一次工作,但在随后的运行中失败并出现此错误。