WSO2 EI 6.6.0自定义SOAP签名中介抛出ClassCastException问题
WSO2 EI 6.6.0 SOAP签名中介部署后ClassCastException异常问题
我使用WSO2 EI 6.6.0开发了一个SOAP信封签名中介,代码在Java SE环境测试完全正常,但部署到WSO2 EI后无法运行,抛出类转换异常。
异常触发代码片段
private static Document sign(Document doc, String Reference) throws Exception { DOMSignContext dsc = null; String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI"); Provider provider = (Provider) Class.forName(providerName).newInstance(); // 该行抛出异常 XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", provider); // ...省略后续签名逻辑 return doc; }
错误堆栈信息
java.lang.ClassCastException: class org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory cannot be cast to class javax.xml.crypto.dsig.XMLSignatureFactory (org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory is in module java.xml.crypto of loader 'platform'; javax.xml.crypto.dsig.XMLSignatureFactory is in unnamed module of loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @657e3cda) at javax.xml.crypto.dsig.XMLSignatureFactory.findInstance(XMLSignatureFactory.java:202) at javax.xml.crypto.dsig.XMLSignatureFactory.getInstance(XMLSignatureFactory.java:250) at x.signer.util.Utils.sign(Utils.java:246) at x.signer.util.Utils.insertSignSoap(Utils.java:233) at x.signer.util.Utils.insertSignSayad(Utils.java:197) at x.signer.Signer.mediate(Signer.java:37) at org.apache.synapse.mediators.ext.ClassMediator.mediate(ClassMediator.java:94) at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:109) at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:71) at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:158) at org.apache.synapse.rest.Resource.process(Resource.java:331) at org.apache.synapse.rest.API.process(API.java:441) at org.apache.synapse.rest.RESTRequestHandler.apiProcess(RESTRequestHandler.java:135) at org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:113) at org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:71) at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:327) at org.apache.synapse.core.axis2.SynapseMessageReceiver.receive(SynapseMessageReceiver.java:98) at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180) at org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:368) at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:427) at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:182) at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834)
输入示例
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <InquiryCode xmlns="http://tempuri.org/"> <RequestCode>12345</RequestCode> </InquiryCode> </S:Body> </S:Envelope>
我已经搜索了大量相关问题,尝试过论坛及StackOverflow上的相关方案,但都没有解决问题。
解决方案
这个异常是类加载器隔离导致的:WSO2 EI基于OSGi运行,javax.xml.crypto.dsig.XMLSignatureFactory由OSGi类加载器加载,而org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory由JDK平台类加载器加载,两个类加载器加载的类无法互相转换。
解决步骤如下:
- 避免手动指定JDK内置Provider:不要显式实例化
org.jcp.xml.dsig.internal.dom.XMLDSigRI,改用无Provider参数的XMLSignatureFactory.getInstance("DOM"),让系统自动选择兼容的Provider。
修改后的代码:private static Document sign(Document doc, String Reference) throws Exception { DOMSignContext dsc = null; // 移除手动指定Provider的逻辑 XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); // ...后续签名逻辑保持不变 return doc; } - 检查依赖包冲突:如果项目中引入了
xmlsec或其他XML签名相关的第三方依赖,需要排除这些依赖,避免和WSO2 EI内置的类冲突。 - 配置OSGi类加载策略:如果必须使用自定义Provider,需要在WSO2 EI的
carbon.properties中添加配置,让OSGi类加载器优先使用JDK平台类加载器加载相关包:
修改后重启WSO2 EI。org.osgi.framework.system.packages.extra=javax.xml.crypto,javax.xml.crypto.dsig,javax.xml.crypto.dsig.dom,javax.xml.crypto.dsig.keyinfo,javax.xml.crypto.dsig.spec
优先推荐第一种方案,因为WSO2 EI已经内置了兼容的XML签名Provider,无需手动指定JDK的内置实现。
内容的提问来源于stack exchange,提问作者hesam
相关产品推荐
相关产品推荐

