CXF学习二(WS-Security)

来源:互联网 发布:centos 启动u盘 编辑:程序博客网 时间:2024/05/29 18:03

在上一篇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> passwords=new HashMap<String, String>();

public ClientPasswordCallback(){
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];
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());
}
}
}