cxf + spring 的WS-Security示例

在按照網上的例子進行配置用戶名令牌的例子,在server端的回調函數中獲取的password 卻一直是空,搜索了好半天,才找到(這個是MD5加密的):java

WSPasswordCallback 的passwordType屬性和password 屬性都爲null,你只能得到用戶名(identifier),通常這裏的邏輯是使用這個用戶名到數據庫中查詢其密碼,而後再設置到password 屬性,WSS4J 會自動比較客戶端傳來的值和你設置的這個值。你可能會問爲何這裏CXF 不把客戶端提交的密碼傳入讓咱們在ServerPasswordCallbackHandler 中比較呢?這是由於客戶端提交過來的密碼在SOAP 消息中已經被加密爲MD5 的字符串,若是咱們要在回調方法中做比較,那麼第一步要作的就是把服務端準備好的密碼加密爲MD5 字符串,因爲MD5 算法參數不一樣結果也會有差異,另外,這樣的工做CXF 替咱們完成不是更簡單嗎?web

 

根據上面說的,我獲取的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");
          }
      }    
    
 }

如下是源代碼:spring

HelloWorld.java數據庫

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


HelloWorldImpl.javaapache

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 .javaapp

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.xmljsp

<?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.xmlide

<?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);
    }
}
相關文章
相關標籤/搜索