JBOSS を使用して CXF で WS を作成しました。私の要件は、X509 証明書を有効にし、CXF クライアントを使用して WS を呼び出すことです。私はWSを作成し、クライアントでそれを正常に呼び出すことができますが、X509を実装するとエラーが発生します:- "Caused by: java.lang.ClassNotFoundException: org.apache.cxf.jaxws.EndpointImpl from [Module "deployment. 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
クライアントのクラスパスに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
クライアントコード
TestCXF.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:]
この問題を解決する方法を提案していただきありがとうございます。どんな助けでも大歓迎です。
--- 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;
}
}