CXF的版本是2.6.1的
服务端回调Java代码:
ServerAuthHandler.java
package com.jysd.ms.entity;
import java.io.IOException;
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 ServerAuthHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
if(pc.getIdentifier().equals("jysd")){
pc.setPassword("jysdsoft");
if(!pc.getPassword().equals("jysdsoft")){
System.out.println("密码错误");
throw new SecurityException("密码错误!");
}
} else {
System.out.println("用户名错误");
throw new SecurityException("用户名错误!");
}
}
}
服务端spring配置文件:
bean.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.jysd"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="bjjysd"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<jaxws:endpoint
id="csh"
implementor="com.jysd.ms.service.imp.UserServiceImpl"
address="/csh" >
<!--配置拦截器-->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<!-- <bean class="org.web.soapHeader.ReadSoapHeader"/>-->
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor" >
<constructor-arg >
<map >
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackClass" value="com.jysd.ms.entity.ServerAuthHandler" />
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
<!--配置拦截器结束 -->
</jaxws:endpoint>
</beans>
客户端回调java代码:
ClientAuthHandler.java
package com.jysd.ms.client;
import java.io.IOException;
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 ClientAuthHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
int usage = pc.getUsage();
System.out.println("identifier: "+pc.getIdentifier());
System.out.println("usage: "+pc.getUsage());
if(usage == WSPasswordCallback.USERNAME_TOKEN){
pc.setPassword("jysdsoft");
}
}
}
客户端spring配置:
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- START SNIPPET: beans -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schema/jaxws.xsd">
<bean id="client" class="com.jysd.ms.UserService"
factory-bean="clientFactory" factory-method="create"/>
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="address" value="http://localhost:8080/CSHServer/csh"/>
<property name="serviceClass" value="com.jysd.ms.UserService"/>
<property name="outInterceptors">
<list>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<!-- <bean class="org.web.soapHeader.AddSoapHeader"/> -->
<bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor" >
<constructor-arg >
<map >
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="user" value="jysd" />
<entry key="passwordCallbackRef" value="com.jysd.ms.entity.ClientAuthHandler" />
</map>
</constructor-arg>
</bean>
</list>
</property>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<!-- START SNIPPET: beans -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schema/jaxws.xsd">
<bean id="client" class="com.jysd.ms.UserService"
factory-bean="clientFactory" factory-method="create"/>
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="address" value="http://localhost:8080/CSHServer/csh"/>
<property name="serviceClass" value="com.jysd.ms.UserService"/>
<property name="outInterceptors">
<list>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<!-- <bean class="org.web.soapHeader.AddSoapHeader"/> -->
<bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor" >
<constructor-arg >
<map >
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="user" value="jysd" />
<entry key="passwordCallbackRef" value="com.jysd.ms.entity.ClientAuthHandler" />
</map>
</constructor-arg>
</bean>
</list>
</property>
</bean>
</beans>
客户端运行:
package com.jysd.ms.client;
import java.util.HashMap;
import java.util.Map;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jysd.ms.UserInfo;
import com.jysd.ms.UserService;
@SuppressWarnings("all")
public class Client {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
UserService us=(UserService) context.getBean("client");
String name = us.getName(new Integer(1));
System.out.println("id=1, name="+name);
}
}
在没有配置WSS4JOutInterceptor的时候,运行main方法的时候可以运行,并能打印,浏览器能访问并返回信息。
在配置WSS4JOutInterceptor之后,浏览器也能访问并返回信息,但当运行main方法报异常,异常代码如下:
警告: Interceptor for {http://service.ms.jysd.com/}UserServiceService#{http://service.ms.jysd.com/}getName has thrown exception, unwinding now
java.lang.ClassCastException: java.lang.String cannot be cast to javax.security.auth.callback.CallbackHandler
at org.apache.ws.security.handler.WSHandler.getCallbackHandler(WSHandler.java:858)
at org.apache.ws.security.handler.WSHandler.getPasswordCallbackHandler(WSHandler.java:879)
at org.apache.ws.security.action.UsernameTokenAction.execute(UsernameTokenAction.java:35)
at org.apache.ws.security.handler.WSHandler.doSenderAction(WSHandler.java:202)
at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor.access$200(WSS4JOutInterceptor.java:52)
at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor$WSS4JOutInterceptorInternal.handleMessage(WSS4JOutInterceptor.java:260)
at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor$WSS4JOutInterceptorInternal.handleMessage(WSS4JOutInterceptor.java:136)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:532)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:464)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:367)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:320)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:89)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
at $Proxy39.getName(Unknown Source)
at com.jysd.ms.client.Client.main(Client.java:27)
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: java.lang.String cannot be cast to javax.security.auth.callback.CallbackHandler
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)
at $Proxy39.getName(Unknown Source)
at com.jysd.ms.client.Client.main(Client.java:27)
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to javax.security.auth.callback.CallbackHandler
at org.apache.ws.security.handler.WSHandler.getCallbackHandler(WSHandler.java:858)
at org.apache.ws.security.handler.WSHandler.getPasswordCallbackHandler(WSHandler.java:879)
at org.apache.ws.security.action.UsernameTokenAction.execute(UsernameTokenAction.java:35)
at org.apache.ws.security.handler.WSHandler.doSenderAction(WSHandler.java:202)
at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor.access$200(WSS4JOutInterceptor.java:52)
at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor$WSS4JOutInterceptorInternal.handleMessage(WSS4JOutInterceptor.java:260)
at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor$WSS4JOutInterceptorInternal.handleMessage(WSS4JOutInterceptor.java:136)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:532)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:464)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:367)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:320)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:89)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
... 2 more
有哪位大神可以指点一下?