我已经使用 JBOSS 在 CXF 中创建了一个 WS,我的要求是我想启用 X509 证书并使用 CXF 客户端调用 WS。我能够创建 WS 并能够成功地使用客户端调用它,但是当我实现 X509 时出现错误:-“原因:来自 [模块”部署的 java.lang.ClassNotFoundException:org.apache.cxf.jaxws.EndpointImpl。 cxfpoc.war:main" from Service Module Loader]" ,下面是相同的详细信息。
我的环境:
应用服务器:JBOSS-AS7.1.1.Final JAVA:1.7
对于 X509 实现,我遵循以下步骤:
1) 在密钥库中使用 testUser/testPass 生成私钥
keytool -genkey -alias testUser -keypass testPass -keystore privatestore.jks -storepass changeit -dname "cn=testUser" -keyalg RSA
2)自签名证书
keytool -selfcert -alias testUser -keystore privatestore.jks -storepass changeit -keypass testPass
3)
keytool -export -alias testUser -file key.rsa -keystore privatestore.jks -storepass changeit
4) 生成公钥存储
keytool -import -alias testUser -file key.rsa -keystore publicstore.jks -storepass changeit
现在我已经复制了服务器的 WEB-INF/classes 文件夹中的 publicstore.jks 文件,并且还复制了 server.properties 文件:
服务器属性
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=changeit
org.apache.ws.security.crypto.merlin.keystore.file=publicstore.jks
现在下面是 Web 服务的代码:
Web 服务的服务器源
package ws;
import java.util.HashMap;
import java.util.Map;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.ws.security.handler.WSHandlerConstants;
@WebService(name = "DemoCXF", serviceName = "DemoCXFService", portName = "DemoCXFPort", targetNamespace = "http://test.org")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class DemoCXF {
@WebMethod()
@WebResult(targetNamespace = "http://test.org", name = "updatedEmployee")
public Employee processEmployeeSalary(
@WebParam(partName = "employee", name = "employee", targetNamespace = "http://test.org")
Employee emp,
@WebParam(partName = "incrementAmount", name = "incrementAmount", targetNamespace = "http://test.org")
Long incrementAmount) {
Map<String,Object> inProps= new HashMap<String,Object>();
inProps.put(WSHandlerConstants.ACTION, "Signature");
inProps.put(WSHandlerConstants.SIG_PROP_FILE, "server.properties");
EndpointImpl jaxWsEndpoint = (EndpointImpl) EndpointImpl.publish(WSDL_URL, new DemoCXF());
Endpoint cxfEndpoint = jaxWsEndpoint.getServer().getEndpoint();
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
cxfEndpoint.getInInterceptors().add(wssIn);
System.out.println("[DemoCXF] Method Invoked....processEmployeeSalary");
System.out.println("[DemoCXF] Before processing: " + emp);
long incrementedSalary = emp.getEmpSalary() + incrementAmount;
emp.setEmpSalary(incrementedSalary);
System.out.println("[DemoCXF] After processing: " + emp);
return emp;
}
}
WS 可使用 URL 访问:cxfpoc?wsdl
现在对于 cilent 部分,我正在使用下面的属性文件和 privatestore.jks
client_sign.properties
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=changeit
org.apache.ws.security.crypto.merlin.keystore.alias=testUser
org.apache.ws.security.crypto.merlin.keystore.file=privatestore.jks
我在 Client 的类路径中放了 JAR 的下面:-
commons-logging-1.1.1.jar
DemoCXFClient.jar [ Generated Client ]
neethi-3.0.1.jar
wsdl4j-1.6.2.jar
wss4j-1.6.5.jar
xmlschema-core-2.0.jar
xmlsec-1.5.1.jar
and CFX jars from jboss-as-7.1.1.Final\modules\org\apache\cxf\main folder
客户代码
测试CXF.java
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.handler.WSHandlerConstants;
import client.DemoCXF;
import client.DemoCXFService;
import client.Employee;
public class TestCXF {
public static void main(String ar[]) throws Exception {
String WSDL_URL= arr[0] + "/cxfpoc?wsdl";
DemoCXFService service=new DemoCXFService(new URL(WSDL_URL));
DemoCXF port=service.getDemoCXFPort();
Client client = ClientProxy.getClient(port);
client.getInInterceptors().add(new LoggingInInterceptor());
client.getOutInterceptors().add(new LoggingOutInterceptor());
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put(WSHandlerConstants.MUST_UNDERSTAND, "0");
outProps.put(WSHandlerConstants.ACTION, "Signature");
outProps.put(WSHandlerConstants.USER, "testUser");
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, KeystorePasswordCallback.class.getName());
outProps.put(WSHandlerConstants.SIG_PROP_FILE, "client_sign.properties");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
cxfEndpoint.getOutInterceptors().add(wssOut);
Employee emp=new Employee();
emp.setEmpNo(1000L);
emp.setEmpName("MiddlewaremagicEmployee");
emp.setEmpSalary(6000L);
System.out.println("\n\nBefore EmpNo: "+emp.getEmpNo()+", Name:"+emp.getEmpName()+", Sal:"+emp.getEmpSalary());
emp=port.processEmployeeSalary(emp,1000L);
System.out.println("\n\nAfter EmpNo: "+emp.getEmpNo()+", Name:"+emp.getEmpName()+", Sal:"+emp.getEmpSalary());
}
}
KeystorePasswordCallback.java
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class KeystorePasswordCallback implements CallbackHandler {
private Map<String, String> passwords = new HashMap<String, String>();
public KeystorePasswordCallback() {
passwords.put("testUser", "testPass");
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
if (pc.getIdentifier().equals("testUser")) {
// set the password on the callback. This will be compared to the
// password which was sent from the client.
pc.setPassword("testPass");
}
}
}
/**
* Add an alias/password pair to the callback mechanism.
*/
public void setAliasPassword(String alias, String password) {
passwords.put(alias, password);
}
}
当我运行客户端程序时,出现以下异常:
20:11:49,296 ERROR [org.jboss.ws.common.invocation.InvocationHandlerJAXWS] (http--127.0.0.1-8080-2) Method invocation failed with exception: null: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0]
at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0]
at org.jboss.ws.common.invocation.AbstractInvocationHandlerJSE.invoke(AbstractInvocationHandlerJSE.java:111)
at org.jboss.wsf.stack.cxf.JBossWSInvoker._invokeInternal(JBossWSInvoker.java:181)
at org.jboss.wsf.stack.cxf.JBossWSInvoker.invoke(JBossWSInvoker.java:127)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0]
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) [rt.jar:1.7.0]
at java.util.concurrent.FutureTask.run(FutureTask.java:166) [rt.jar:1.7.0]
at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:106)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:207)
at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:91)
at org.jboss.wsf.stack.cxf.transport.ServletHelper.callRequestHandler(ServletHelper.java:169)
at org.jboss.wsf.stack.cxf.CXFServletExt.invoke(CXFServletExt.java:87)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:185)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:108)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.jboss.wsf.stack.cxf.CXFServletExt.service(CXFServletExt.java:135)
at org.jboss.wsf.spi.deployment.WSFServlet.service(WSFServlet.java:140) [jbossws-spi-2.0.3.GA.jar:2.0.3.GA]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0]
Caused by: java.lang.NoClassDefFoundError: org/apache/cxf/jaxws/EndpointImpl
at ws.DemoCXF.processEmployeeSalary(DemoCXF.java:37) [classes:]
... 38 more
Caused by: java.lang.ClassNotFoundException: org.apache.cxf.jaxws.EndpointImpl from [Module "deployment.cxfpoc.war:main" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120)
... 39 more
20:11:49,359 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (http--127.0.0.1-8080-2) Application {http://test.org}DemoCXFService#{http://test.org}processEmployeeSalary has thrown exception, unwinding now: org.apache.cxf.interceptor.Fault: org/apache/cxf/jaxws/EndpointImpl
at org.jboss.wsf.stack.cxf.JBossWSInvoker.createFault(JBossWSInvoker.java:246)
at org.jboss.wsf.stack.cxf.JBossWSInvoker._invokeInternal(JBossWSInvoker.java:201)
at org.jboss.wsf.stack.cxf.JBossWSInvoker.invoke(JBossWSInvoker.java:127)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0]
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) [rt.jar:1.7.0]
at java.util.concurrent.FutureTask.run(FutureTask.java:166) [rt.jar:1.7.0]
at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:106)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:207)
at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:91)
at org.jboss.wsf.stack.cxf.transport.ServletHelper.callRequestHandler(ServletHelper.java:169)
at org.jboss.wsf.stack.cxf.CXFServletExt.invoke(CXFServletExt.java:87)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:185)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:108)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.jboss.wsf.stack.cxf.CXFServletExt.service(CXFServletExt.java:135)
at org.jboss.wsf.spi.deployment.WSFServlet.service(WSFServlet.java:140) [jbossws-spi-2.0.3.GA.jar:2.0.3.GA]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
感谢建议我如何解决这个问题,我被困在这个问题上已经 3 天了。任何帮助都深表感谢。
--- 2013 年 5 月 5 日 --- 使用下面的服务器代码运行良好,WS 被调用,没有任何错误,但拦截器在这种情况下不起作用,意味着没有验证安全性..让我知道我该如何解决这个问题。
package ws;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.ws.security.handler.WSHandlerConstants;
@WebService(name = "DemoCXF", serviceName = "DemoCXFService", portName = "DemoCXFPort", targetNamespace = "http://test.org")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class DemoCXF implements DemoCXFI{
@WebMethod()
@WebResult(targetNamespace = "http://test.org", name = "updatedEmployee")
public Employee processEmployeeSalary(
@WebParam(partName = "employee", name = "employee", targetNamespace = "http://test.org") Employee emp,
@WebParam(partName = "incrementAmount", name = "incrementAmount", targetNamespace = "http://test.org") Long incrementAmount) {
Map<String, Object> inProps = new HashMap<String, Object>();
inProps.put(WSHandlerConstants.ACTION, "Signature");
inProps.put(WSHandlerConstants.SIG_PROP_FILE, "server.properties");
inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, KeystorePasswordCallback.class.getName());
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
System.out.println("[DemoCXF] Method STEP1");
// Endpoint cxfEndpoint = null;
try {
//EndpointImpl jaxWsEndpoint = (EndpointImpl)
// EndpointImpl.publish("http://localhost:8080/cxfpoc?wsdl",DemoCXFI.class);
Service cxfService = Service.create(new URL(
"http://localhost:8080/cxfpoc?wsdl"), new QName(
"http://test.org", "DemoCXFService"));
DemoCXFI mySer = cxfService.getPort(DemoCXFI.class);
Client client = ClientProxy.getClient(mySer);
client.getInInterceptors().add(new LoggingInInterceptor());
client.getOutInterceptors().add(new LoggingOutInterceptor());
Endpoint cxfEndpoint = client.getEndpoint();
System.out.println("[DemoCXF] Method STEP2");
// Endpoint cxfEndpoint = jaxWsEndpoint.getServer().getEndpoint();
System.out.println("[DemoCXF] Method STEP3");
System.out.println("[DemoCXF] Method STEP4");
cxfEndpoint.getInInterceptors().add(wssIn);
cxfEndpoint.getInInterceptors().add(new LoggingInInterceptor());
cxfEndpoint.getOutInterceptors().add(new LoggingOutInterceptor());
System.out
.println("[DemoCXF] Method Invoked....processEmployeeSalary");
System.out.println("[DemoCXF] Before processing: " + emp);
long incrementedSalary = emp.getEmpSalary() + incrementAmount;
emp.setEmpSalary(incrementedSalary);
System.out.println("[DemoCXF] After processing: " + emp);
} catch (Exception ex) {
ex.printStackTrace();
}
// Below line is having error//
/*
* EndpointImpl jaxWsEndpoint = (EndpointImpl)
* EndpointImpl.publish("http://localhost:8085/cxfpoc", new DemoCXF());
*/
// Some Business Logic to Store the Employee's Updated Details in
// Database or Messaging System.
return emp;
}
}