cxf + spring 的WS-Security示例

在按照网上的例子进行配置用户名令牌的例子,在server端的回调函数中获取的password 却一直是空,搜索了好半天,才找到(这个是MD5加密的):

WSPasswordCallback 的passwordType属性和password 属性都为null,你只能获得用户名(identifier),一般这里的逻辑是使用这个用户名到数据库中查询其密码,然后再设置到password 属性,WSS4J 会自动比较客户端传来的值和你设置的这个值。你可能会问为什么这里CXF 不把客户端提交的密码传入让我们在ServerPasswordCallbackHandler 中比较呢?这是因为客户端提交过来的密码在SOAP 消息中已经被加密为MD5 的字符串,如果我们要在回调方法中作比较,那么第一步要做的就是把服务端准备好的密码加密为MD5 字符串,由于MD5 算法参数不同结果也会有差别,另外,这样的工作CXF 替我们完成不是更简单吗?

 

根据上面说的,我获取的password 为null,所以这里就不用自己判断密码了,只要验证用户名后,在设置密码就可以自动验证了,代码如下:

01 public class ServerPasswordCallback implements CallbackHandler {   
02      
03      public void handle(Callback[] callbacks) throws IOException,   
04               UnsupportedCallbackException {   
05           WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];   
06           String pw = pc.getPassword();   
07           String idf = pc.getIdentifier();   
08           System.out.println("password:"+pw);   
09           System.out.println("identifier:"+idf); 
10           if(idf.endsWith("admin")){
11            pc.setPassword("admin");
12           }
13       }   
14      
15  }

以下是源代码:

HelloWorld.java

1 package com.mms.webservice;
2 import javax.jws.WebService;
3 @WebService
4 public interface HelloWorld {
5     String sayHi(String text);
6 }


    HelloWorldImpl.java

    01 package com.mms.webservice;
    02 import javax.annotation.Resource;
    03 import javax.jws.WebService;
    04 import javax.servlet.http.HttpServletRequest;
    05 import javax.servlet.http.HttpSession;
    06 import javax.xml.ws.WebServiceContext;
    07 import javax.xml.ws.handler.MessageContext;
    08 import org.apache.cxf.transport.http.AbstractHTTPDestination;
    09  
    10 @WebService
    11 public class HelloWorldImpl implements HelloWorld {
    12     public String sayHi(String text) {
    13         return "Hello " + text;
    14     }
    15 }



    ServerPasswordCallback.java

    01 package com.mms.webservice.test;
    02 import java.io.IOException;
    03 import java.util.HashMap;
    04 import java.util.Map;
    05 import javax.security.auth.callback.Callback;
    06 import javax.security.auth.callback.CallbackHandler;
    07 import javax.security.auth.callback.UnsupportedCallbackException;
    08 import org.apache.ws.security.WSPasswordCallback;
    09 import org.apache.ws.security.WSSecurityException;
    10  
    11 public class ServerPasswordCallback implements CallbackHandler {
    12  
    13     private Map<String, String> passwords = new HashMap<String, String>();
    14  
    15     public ServerPasswordCallback() {
    16         passwords.put("admin""admin");
    17         passwords.put("test""test");
    18     }
    19  
    20     public void handle(Callback[] callbacks) throws IOException,
    21             UnsupportedCallbackException {
    22         System.out.println("server:callbacks.length-"+callbacks.length);
    23         for (int i = 0; i < callbacks.length; i++) {
    24             WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
    25             if (!passwords.containsKey(pc.getIdentifier()))
    26                 try {
    27                     throw new WSSecurityException("user not match");
    28                 catch (WSSecurityException e) {
    29                     e.printStackTrace();
    30                 }
    31             String pass = passwords.get(pc.getIdentifier());
    32             pc.setPassword(pass);
    33         }
    34     }
    35  
    36 }


      ClientPasswordCallback .java

      01 package com.mms.client;
      02 import java.io.IOException;
      03 import java.util.HashMap;
      04 import java.util.Map;
      05 import javax.security.auth.callback.Callback;
      06 import javax.security.auth.callback.CallbackHandler;
      07 import javax.security.auth.callback.UnsupportedCallbackException;
      08 import org.apache.ws.security.WSPasswordCallback;
      09 import org.apache.ws.security.WSSecurityException;
      10  
      11 public class ClientPasswordCallback implements CallbackHandler {
      12  
      13     private Map<String, String> passwords = new HashMap<String, String>();
      14  
      15     public ClientPasswordCallback() {
      16         passwords.put("admin""admin");
      17         passwords.put("test""test");
      18     }
      19  
      20     public void handle(Callback[] callbacks) throws IOException,
      21             UnsupportedCallbackException {
      22         System.out.println("client:callbacks.length-"+callbacks.length);
      23         for (int i = 0; i < callbacks.length; i++) {
      24             WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
      25             int usage = pc.getUsage();
      26             if (!passwords.containsKey(pc.getIdentifier()))
      27                 try {
      28                     throw new WSSecurityException("user not exists ");
      29                 catch (WSSecurityException e) {
      30                     e.printStackTrace();
      31                 }
      32             String pass = passwords.get(pc.getIdentifier());
      33             if (usage == WSPasswordCallback.USERNAME_TOKEN && pass != null) {
      34                 System.out.println("client:pass"+pass);
      35                 pc.setPassword(pass);
      36                 return;
      37             }
      38         }
      39     }
      40  
      41 }

      web.xml

      01 <?xml version="1.0" encoding="UTF-8"?>
      02 <web-app version="2.5"
      03     xmlns="http://java.sun.com/xml/ns/javaee"
      04     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      05     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      06     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      07   <welcome-file-list>
      08     <welcome-file>index.jsp</welcome-file>
      09   </welcome-file-list>
      10   <context-param>
      11         <param-name>contextConfigLocation</param-name>
      12         <param-value>
      13             classpath:server.xml classpath:client.xml
      14         </param-value>
      15     </context-param>
      16  
      17     <listener>
      18         <listener-class>
      19             org.springframework.web.context.ContextLoaderListener
      20         </listener-class>
      21     </listener>
      22  
      23     <servlet>
      24         <servlet-name>CXFServlet</servlet-name>
      25         <servlet-class>
      26             org.apache.cxf.transport.servlet.CXFServlet
      27         </servlet-class>
      28     </servlet>
      29  
      30     <servlet-mapping>
      31         <servlet-name>CXFServlet</servlet-name>
      32         <url-pattern>/*</url-pattern>
      33     </servlet-mapping>
      34 </web-app>

      客户端spring配置文件:client.xml

      01 <?xml version="1.0" encoding="UTF-8"?>
      02 <beans xmlns="http://www.springframework.org/schema/beans"
      03     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
      04     xsi:schemaLocation="
      05                        http://www.springframework.org/schema/beans
      06                        http://www.springframework.org/schema/beans/spring-beans.xsd
      07                        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
      08  
      09     <!-- 定义客户端的拦截器对象  -->
      10     <bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
      11     <bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
      12     <bean id="saajOut" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
      13     <!-- <bean id="soapheaderOut" class="com.mms.client.writeSOAPHeaderInterceptor" /> -->
      14     <bean id="wss4jOut" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
      15         <constructor-arg>
      16             <map>
      17                 <entry key="action" value="UsernameToken" />
      18                 <entry key="passwordType" value="PasswordText" />
      19                 <entry key="user" value="admin" />
      20                 <entry key="passwordCallbackClass" value="com.mms.client.ClientPasswordCallback" />
      21             </map>
      22         </constructor-arg>
      23     </bean>
      24     <!-- 客户端的配置 -->
      25     <jaxws:client id="client" serviceClass="com.mms.webservice.HelloWorld" address="http://127.0.0.1:8080/CXFSecurity/HelloWorld">
      26         <jaxws:inInterceptors>
      27             <ref bean="logIn" />
      28         </jaxws:inInterceptors>
      29         <jaxws:outInterceptors>
      30             <ref bean="logOut" />
      31             <ref bean="saajOut" />
      32             <!--<ref bean="soapheaderOut" /> -->
      33             <ref bean="wss4jOut" />
      34         </jaxws:outInterceptors>
      35     </jaxws:client>
      36 </beans>

      服务器spring配置文件:server.xml

      01 <beans xmlns="http://www.springframework.org/schema/beans"
      02     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
      03     xsi:schemaLocation="
      04 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      05 http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
      06     <!-- jar包中自带的cxf文件夹下的*.xml文件 -->
      07     <import resource="classpath:META-INF/cxf/cxf.xml" />
      08     <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
      09     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
      10     <!-- 定义服务端的拦截器对象 -->
      11     <bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
      12     <bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
      13     <bean id="saajIn" class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
      14     <!-- <bean id="soapheaderIn" class="com.mms.webservice.test.readSOAPHeaderInterceptor" /> -->
      15     <bean id="wss4jIn" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
      16         <constructor-arg>
      17             <map>
      18                 <entry key="action" value="UsernameToken" />
      19                 <entry key="passwordType" value="PasswordText" />
      20                 <entry key="passwordCallbackClass" value="com.mms.webservice.test.ServerPasswordCallback" />
      21             </map>
      22         </constructor-arg>
      23     </bean>
      24     <jaxws:endpoint id="helloWorld" implementor="com.mms.webservice.HelloWorldImpl"
      25         address="/HelloWorld">
      26         <jaxws:inInterceptors>
      27             <ref bean="logIn" />
      28             <ref bean="saajIn" />
      29             <!--<ref bean="soapheaderIn" /> -->
      30             <ref bean="wss4jIn" />
      31         </jaxws:inInterceptors>
      32         <jaxws:outInterceptors>
      33             <ref bean="logOut" />
      34         </jaxws:outInterceptors>
      35     </jaxws:endpoint>
      36  
      37 </beans>

      测试Client.java

      01 package com.mms.client;
      02 import org.springframework.context.ApplicationContext;
      03 import org.springframework.context.support.ClassPathXmlApplicationContext;
      04 import com.mms.webservice.HelloWorld;
      05  
      06 public final class Client {
      07  
      08     private Client() {
      09     }
      10  
      11     public static void main(String args[]) throws Exception {
      12                 ApplicationContext  context = new ClassPathXmlApplicationContext(
      13                 new String[] { "client.xml" });
      14         HelloWorld client = (HelloWorld) context.getBean("client");
      15         String response = client.sayHi("hello test!");
      16         System.out.println("Response: " + response);
      17     }
      18 }
      • 1
        点赞
      • 1
        收藏
        觉得还不错? 一键收藏
      • 0
        评论

      “相关推荐”对你有帮助么?

      • 非常没帮助
      • 没帮助
      • 一般
      • 有帮助
      • 非常有帮助
      提交
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值