在上一篇CXF学习一中介绍了如何创建Server及Client,创建好Webservice之后部署到服务器就可以供其它的应用去访问,但在网络上不安全,任何的应用都可以去访问。为了保证Webservice的安全性,需要对Webservice提供认证,认证通过之后才可以访问服务,创建安全认证的步骤如下:
?一、在Server端创建用户验证回调函数,回调函数如下:
public class ServerPasswordCallback implements CallbackHandler {
private Map<String,String> passwords=new HashMap<String,String>();
//在构造函数中初始化用户名和密码
public ServerPasswordCallback(){
passwords.put("test","1234");
passwords.put("admin","123");
passwords.put("test1","storepassword");
}
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for(int i=0;i<callbacks.length;i++){
WSPasswordCallback pc=(WSPasswordCallback)callbacks[i];
if(!passwords.containsKey(pc.getIdentifier()))
throw new WSSecurityException(" user name not match");
String password=passwords.get(pc.getIdentifier());
String pwd=pc.getPassword();
if(pwd==null||!pwd.equals(password)){
throw new WSSecurityException("password not match");
}
}
}
}
二、在Server端的applicationContext-cxf.xml文件中配置拦截器和回调函数,文件内容如下
<?xml version="1.0" encoding="UTF-8"?>
<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/schemas/jaxws.xsd">
<!-- Load CXF modules from cxf.jar -->
? ? <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" /> ?
<jaxws:endpoint ?id="order"?
? implementor="cn.com.demo.order.service.impl.OrderServiceImpl"
? address="/cxfOrder">
? ? ? ? ? ? ? ? ? ? ? ?<!-- 拦截器 -->
<jaxws:inInterceptors>
<ref bean="wss4Jinterceptor" />
</jaxws:inInterceptors>
</jaxws:endpoint>
<!-- ? 服务端用户认证回调函数-->
<bean id="serverPasswordCallback" class="cn.com.demo.order.service.security.ServerPasswordCallback" />
<!--配置服务端拦截器-->
<bean id="wss4Jinterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor" >
<constructor-arg>
? ? ? ? ? ? <map>
? <!--指定用户令牌-->
? ? ? ? ? ? ? ?<entry key="action" value="UsernameToken"/>
? ? ? ? ? ? ? ? ? ?<!-- 指定密码为文本格式 ? 也可指定为 PasswordDigest?-->
? ? ? ? ? ? ? ?<entry key="passwordType" value="PasswordText"/>
? ? ? ? ? ? ? ? ? ?<!-- 指定密码认证回调函数-->
? ? ? ? ? ? ? ?<entry key="passwordCallbackRef">
? ? ? ? ? ? ? ? ? <ref bean="serverPasswordCallback"/>
? ? ? ? ? ? ? ?</entry>
? ? ? ? ? ? </map>
? ? ? ? ?</constructor-arg>
</bean>
</beans>
二、在Client创建密码认证回调函数
public class ClientPasswordCallback implements CallbackHandler {
private Map<String,String>();
public ClientPasswordCallback(){
passwords.put("test","storepassword");
}
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for(int i=0;i<callbacks.length;i++){
WSPasswordCallback pc=(WSPasswordCallback)callbacks[i];
int usage=pc.getUsage();
if(!passwords.containsKey(pc.getIdentifier())){
throw new WSSecurityException("user not exists");
}
String pass=passwords.get(pc.getIdentifier());
if(usage==WSPasswordCallback.USERNAME_TOKEN&&pass!=null){
pc.setPassword(pass);
return;
}
}
}
}
三、在Client中的applicationContext_cxf_client.xml中配置登入、登出拦截器
<?xml version="1.0" encoding="UTF-8"?>
<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/schemas/jaxws.xsd">
? ? ??<!-- client service interface ?-->
? ? ? <bean id="client" class="cn.com.cxf.demo.order.service.OrderProcess" ?factory-bean="clientFactory" factory-method="create" ?/> ?
?<!-- ?apache cxf jaxwsProxyFactorybean ?-->
?<bean id="clientFactory" ?class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean" >
? ?<!-- ?service class ? ? -->
?<property name="serviceClass" value="cn.com.cxf.demo.order.service.OrderProcess" ?/>
?<!-- service address ? -->
?<property name="address" value="http://localhost:8080/orderdemo/services/cxfOrder" />
? <!--登入拦截器--->
?<property name="inInterceptors"> ?
? ? ? ? ? ? ? ? ? <list> ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? <ref bean="logIn" /> ?
? ? ? ? ? ? ? ? ? ?</list> ?
? ? ? ? ? ? ? ? ? </property> ?
? ? ?<!-- 登出拦截器-->
? ? ? ? ? ? ? ? ? ?<property name="outInterceptors"> ?
? ? ? ? ? ? ? ? ? ?<list> ?
? ? ? ? ? ? ? ? <ref bean="logOut" /> ?
? ? ? ? ? ? ? ? <ref bean="saajOut" /> ?
? ? ? ? ? ? ? ? <ref bean="wss4jOut" /> ?
? ? ? ? ? ? </list> ?
? ? ? ? </property> ?
?</bean>
? ? ? ? ? ?<!-- loggingIninterceptor ?-->
<bean id="logIn" ?class="org.apache.cxf.interceptor.LoggingInInterceptor" /> ?
<!-- loggingOutIntercepor -->
? ? ? ? <bean id="logOut" ?class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> ?
<!-- saaJoutInteceptor ? -->
? ? ? ? <bean id="saajOut" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" /> ?
<!-- ?wss4JOutInterceptor ? ?-->
? ? ? ? <bean id="wss4jOut" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"> ?
? ? ? ? <constructor-arg> ?
? ? ? ? ? ? <map> ?
<!--指定用户令牌-->
? ? ? ? ? ? ? ? <entry key="action" value="UsernameToken" /> ?
<!--指定密码为文本格式-->
<entry key="passwordType" value="PasswordText" />
<!--指定用户名为test-->
? ? ? ? ? ? ? ? <entry key="user" value="test" /> ?
<!--指定密码认证回调函数-->
? ? ? ? ? ? ? ? <entry key="passwordCallbackClass" ?
? ? ? ? ? ? ? ? ? ? value="cn.com.cxf.demo.order.service.security.ClientPasswordCallback" /> ?
? ? ? ? ? ? </map> ?
? ? ? ? </constructor-arg> ?
? ? </bean> ??
</beans>
四、创建Client、测试是否认证通过
public class CxfOrderClient { public static void main(String args[]) throws Exception { //读取客户端 Spring 配置文件 ClassPathXmlApplicationContext ?context= new ClassPathXmlApplicationContext(new String[] {"spring/applicationContext_cxf_client.xml"}); //获取客户端的Service接口 OrderProcess clientService=(OrderProcess) context.getBean("client"); clientService.getOrder("11"); System.out.println("===============updateOrder:"+clientService.updateOrder("11")); System.out.println("===============getOrder:"+clientService.getOrder("11").getOrderId()); List<Order> list=clientService.queryOrder(new Date(),new Date()); for(int i=0;i<list.size();i++){ Order order=list.get(i); System.out.println("================queryOrder:"+order.getOrderId()); } } }