在soapheader中添加自定义信息

        有时候我们的webservice在服务端需要做一个调用方的验证,以保证我们的服务只有指定的客户才能使用。虽然可以使用wss4j的方法来做安全验证,但是考虑到我们的项目会与被.net平台下的项目调用,为了避免跨平台间出现的问题,我们还是决定采用自定义soapheader的形式来添加验证信息。

           先来看一下客户端发起请求的soap内容


   
   
      
         
         ?
         
         ?
      
   
其中红字部分就是我们要添加自定义信息的位置,再来看一下客户端的spring配置文件


		
		
		
			
				
				
			
		
	
其中红色部分指定的类就是用来在请求的soap协议中加上自定义头部信息的处理类,处理类内容如下

package tsb.ws.common.authentication;

import java.util.List;
import javax.xml.namespace.QName;

import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * 添加SoapHeader拦截器
 * @author cyf
 *
 */
public class AddSoapHeader extends AbstractSoapInterceptor {
	public AddSoapHeader() {
		super(Phase.WRITE);
	}

	/**
	 * 处理soap信息
	 * @param message soap信息
	 * 

作成者:cyf */ public void handleMessage(SoapMessage message) throws Fault { // SoapHeader部分待添加的节点 QName qName = new QName("CertificationProxy"); Document doc = DOMUtils.createDocument(); // 验证用户名 Element id = doc.createElement("userid"); id.setTextContent("xxx"); // 验证密码 Element pwd = doc.createElement("userpwd"); pwd.setTextContent("xxx"); Element root = doc.createElementNS("http://tempuri.org/","CertificationProxy"); root.appendChild(id); root.appendChild(pwd); // 创建SoapHeader内容 SoapHeader header = new SoapHeader(qName, root); // 添加SoapHeader内容 List

headers = message.getHeaders(); headers.add(header); } }

在调用服务的时候客户端就可以在soap请求的头部添加如下的信息其中userid和userpwd就是我们用来验证的用户名和密码



	
		
			xxx
			xxx
		
	
	
		
			
			?
			
			?
		
	

服务端截取请求soap协议时需要在配置文件中添加拦截器


		 
			
			
			
			
		
		
			
		
		
			
		
	

拦截器内容如下,主要就是从soap协议中获取head部分的节点,然后拿头的值做判断。

package tsb.ws.common.authentication;

import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.NodeList;

public class cnm extends AbstractPhaseInterceptor {

		// 取得Log实例
		private static Log log = LogFactory.getLog(ReadSoapHeader.class);

		private SAAJInInterceptor saa = new SAAJInInterceptor();

		public cnm() {
			super(Phase.PRE_PROTOCOL);
			getAfter().add(SAAJInInterceptor.class.getName());
		}

		@Override
		public void handleMessage(SoapMessage message) throws Fault {
			// 获取soap信息
			SOAPMessage mess = message.getContent(SOAPMessage.class);
			if (mess == null) {				
				saa.handleMessage(message);
				mess = message.getContent(SOAPMessage.class);
			}
			SOAPHeader head = null;
			try {
				head = mess.getSOAPHeader();
			} catch (SOAPException e) {
				e.printStackTrace();
			}
			if (head == null) {
				return;
			}
			try {

				// 读取soap头中的userid节点
				NodeList nodes = head.getElementsByTagName("userid");

				// 读取soap头中的userid节点
				NodeList nodepass = head.getElementsByTagName("userpwd");

				// 此处可加各种验证

			} catch (Exception e) {
				SOAPException soapExc = new SOAPException("验证失败");
				throw new Fault(soapExc);
			}
		}	
}

****************************************************************************************************************************************************

另外也记一下用wss4j的UsernameToken进行验证的配置,基本上和自定义soapheader也差不多同样是采用拦截器的方法

客户端配置文件的endpoint中添加如下拦截器,其中clientPasswordCallback用于指定添加验证信息的处理类;

UsernameToken是指使用用户名令牌;PasswordText指密码加密策略,这里直接文本;xxx 指别名。


	
	
	
		
			
			
				
					
						
						
						
						
							
						
					
				
			
		
	
添加验证信息

package cxf.client;  
import java.io.IOException;  
import javax.security.auth.callback.Callback;  
import javax.security.auth.callback.CallbackHandler;  
import javax.security.auth.callback.UnsupportedCallbackException;  
import org.apache.ws.security.WSPasswordCallback;  
public class ClientPasswordCallback implements CallbackHandler {  
    @Override  
    public void handle(Callback[] callbacks) throws IOException,  
            UnsupportedCallbackException {  
        WSPasswordCallback ws = (WSPasswordCallback) callbacks[0];  
        ws.setPassword("xxxx");  
        ws.setIdentifier("xxxx");  
    }  
}
服务端通过拦截器接收验证信息,serverPasswordCallback表示验证处理的类


	
		
		
		
		
		
			
				
					
					
					
					
						
					
				
			
		
	
	
		
	
	
		
	

服务端获取客户端发来的验证信息方法如下

WSPasswordCallback ws = (WSPasswordCallback) callbacks[0];  
// 获取用户名
String identifier = ws.getIdentifier();  
// 获取用户密码        
String password = ws.getPassword();  







你可能感兴趣的:(在soapheader中添加自定义信息)