cxf + spring 的WS-Security示例

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

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

 

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

public class ServerPasswordCallback implements CallbackHandler {    
    
     public void handle(Callback[] callbacks) throws IOException,    
              UnsupportedCallbackException {    
          WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];    
          String pw = pc.getPassword();    
          String idf = pc.getIdentifier();    
          System.out.println("password:"+pw);    
          System.out.println("identifier:"+idf);  
          if(idf.endsWith("admin")){
           pc.setPassword("admin");
          }
      }    
    
 }

以下是源代码:

HelloWorld.java

package com.mms.webservice;
import javax.jws.WebService;
@WebService
public interface HelloWorld { 
    String sayHi(String text); 
}


HelloWorldImpl.java

package com.mms.webservice;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import org.apache.cxf.transport.http.AbstractHTTPDestination;

@WebService
public class HelloWorldImpl implements HelloWorld {	
    public String sayHi(String text) {
        return "Hello " + text;
    }
}



ServerPasswordCallback.java

package com.mms.webservice.test;
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;
import org.apache.ws.security.WSSecurityException;

public class ServerPasswordCallback implements CallbackHandler {

	private Map<String, String> passwords = new HashMap<String, String>();

	public ServerPasswordCallback() {
		passwords.put("admin", "admin");
		passwords.put("test", "test");
	}

	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		System.out.println("server:callbacks.length-"+callbacks.length);
		for (int i = 0; i < callbacks.length; i++) {
			WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
			if (!passwords.containsKey(pc.getIdentifier()))
				try {
					throw new WSSecurityException("user not match");
				} catch (WSSecurityException e) {
					e.printStackTrace();
				}
			String pass = passwords.get(pc.getIdentifier());
			pc.setPassword(pass);
		}
	}

}


ClientPasswordCallback .java

package com.mms.client;
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;
import org.apache.ws.security.WSSecurityException;

public class ClientPasswordCallback implements CallbackHandler {

	private Map<String, String> passwords = new HashMap<String, String>();

	public ClientPasswordCallback() {
		passwords.put("admin", "admin");
		passwords.put("test", "test");
	}

	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		System.out.println("client:callbacks.length-"+callbacks.length);
		for (int i = 0; i < callbacks.length; i++) {
			WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
			int usage = pc.getUsage();
			if (!passwords.containsKey(pc.getIdentifier()))
				try {
					throw new WSSecurityException("user not exists ");
				} catch (WSSecurityException e) {
					e.printStackTrace();
				}
			String pass = passwords.get(pc.getIdentifier());
			if (usage == WSPasswordCallback.USERNAME_TOKEN && pass != null) {
				System.out.println("client:pass"+pass);
				pc.setPassword(pass);
				return;
			}
		}
	}

}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath:server.xml classpath:client.xml
		</param-value>
	</context-param>

	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>

	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<servlet-class>
			org.apache.cxf.transport.servlet.CXFServlet
		</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

客户端spring配置文件: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">

	<!-- 定义客户端的拦截器对象  -->
	<bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
	<bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
	<bean id="saajOut" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
	<!-- <bean id="soapheaderOut" class="com.mms.client.writeSOAPHeaderInterceptor" /> -->
	<bean id="wss4jOut" 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="admin" />
				<entry key="passwordCallbackClass" value="com.mms.client.ClientPasswordCallback" />
			</map>
		</constructor-arg>
	</bean>
	<!-- 客户端的配置 -->
	<jaxws:client id="client" serviceClass="com.mms.webservice.HelloWorld" address="http://127.0.0.1:8080/CXFSecurity/HelloWorld">
		<jaxws:inInterceptors>
			<ref bean="logIn" />
		</jaxws:inInterceptors>
		<jaxws:outInterceptors>
			<ref bean="logOut" />
			<ref bean="saajOut" />
			<!--<ref bean="soapheaderOut" /> -->
			<ref bean="wss4jOut" />
		</jaxws:outInterceptors>
	</jaxws:client>
</beans>

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

<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">
	<!-- jar包中自带的cxf文件夹下的*.xml文件 -->
	<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" />
	<!-- 定义服务端的拦截器对象 -->
	<bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
	<bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
	<bean id="saajIn" class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
	<!-- <bean id="soapheaderIn" class="com.mms.webservice.test.readSOAPHeaderInterceptor" /> -->
	<bean id="wss4jIn" 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.mms.webservice.test.ServerPasswordCallback" />
			</map>
		</constructor-arg>
	</bean>
	<jaxws:endpoint id="helloWorld" implementor="com.mms.webservice.HelloWorldImpl"
		address="/HelloWorld">
		<jaxws:inInterceptors>
			<ref bean="logIn" />
			<ref bean="saajIn" />
			<!--<ref bean="soapheaderIn" /> -->
			<ref bean="wss4jIn" />
		</jaxws:inInterceptors>
		<jaxws:outInterceptors>
			<ref bean="logOut" />
		</jaxws:outInterceptors>
	</jaxws:endpoint>

</beans> 

测试Client.java

package com.mms.client;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mms.webservice.HelloWorld;

public final class Client {

    private Client() {
    }

    public static void main(String args[]) throws Exception {
                ApplicationContext  context = new ClassPathXmlApplicationContext(
                new String[] { "client.xml" });
        HelloWorld client = (HelloWorld) context.getBean("client");
        String response = client.sayHi("hello test!");
        System.out.println("Response: " + response);
    }
}


你可能感兴趣的:(cxf + spring 的WS-Security示例)