WebService学习笔记(七)自定义拦截器


添加自定义拦截器,CXF允许程序员自己操作SOAP协议。

Envelope可分为两部分,Header(可选) 与Body,通过自定义拦截器,可在Header部分里添加认证信息。


服务端代码:


需要实现PhaseInterceptor,但一般继承抽象类AbstractPhaseInterceptor就可以了。

package com.skymr.hello.ws.interceptor;

import java.util.List;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage>{


	public AuthInterceptor() {
		//调用之前认证
		super(Phase.PRE_INVOKE);
	}
	/**
	 * 取出Header头进行认证
	 */
	public void handleMessage(SoapMessage msg) throws Fault {
		List<Header> headers = msg.getHeaders();
		if(headers == null || headers.size()==0){
			throw new Fault(new IllegalArgumentException("找不到认证信息"));
		}
		Header header = headers.get(0);
		Element auth = (Element)header.getObject();
		NodeList uNl = auth.getElementsByTagName("username");
		NodeList uPw = auth.getElementsByTagName("password");
		if(uNl.getLength() < 1){
			throw new Fault(new IllegalArgumentException("找不到用户名信息"));
		}
		if(uPw.getLength() < 1){
			throw new Fault(new IllegalArgumentException("找不到密码信息"));
		}
		String userName = uNl.item(0).getTextContent();
		String password = uPw.item(0).getTextContent();
		
		if("admin".equals(userName) && "admin".equals(password)){
			System.out.println("认证成功");
		}
		else{
			throw new Fault(new IllegalArgumentException("认证失败"));
		}
	}

}

客户端代码

package com.skymr.hello.ws.interceptor;

import java.util.List;

import javax.xml.namespace.QName;

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

public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage>{

	protected String userName;
	
	protected String password;

	public AuthInterceptor(String userName, String password) {
		//发送前拦截
		super(Phase.PREPARE_SEND);
		this.userName = userName;
		this.password = password;
		
	}
	/**
	 * 生成认证信息
	 * <head>
	 * 	<authrity>
	 * 		<username></username>
	 * 		<password></password>
	 * 	</authrity>
	 * </head>
	 */
	public void handleMessage(SoapMessage msg) throws Fault {
		System.out.println("--------------");
		List<Header> headers = msg.getHeaders();
		Document doc = DOMUtils.createDocument();
		Element auth = doc.createElement("authrity");
		Element userNameNode = doc.createElement("username");
		Element passwordNode = doc.createElement("password");
		userNameNode.setTextContent(userName);
		passwordNode.setTextContent(password);
		auth.appendChild(userNameNode);
		auth.appendChild(passwordNode);
		//QName的参数随便取个名字
		headers.add(0,new Header(new QName("head"), auth));
	}

}

服务端和客户端添加各自拦截器后进行测试:

服务端添加:是在spring与CXF整合的基础上

    <jaxws:endpoint id="helloWorld" implementor="#hello" address="/HelloWorld" />  
    <jaxws:endpoint id="userOp" implementor="#userOperator" address="/UserOperator" ></jaxws:endpoint>
    
    <bean id="logInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
    <!-- 自定义拦截器,认证拦截 -->
    <bean id="authInterceptor" class="com.skymr.hello.ws.interceptor.AuthInterceptor"></bean>
    <cxf:bus>
    	<cxf:inInterceptors>
    		<ref bean="logInterceptor"/>
    		<ref bean="authInterceptor"/>
    	</cxf:inInterceptors>
    </cxf:bus>

客户端添加:

		HelloWorldws factory = new HelloWorldws();
		HelloWorld hw = factory.getHelloWorldBeanPort();
		Client client = ClientProxy.getClient(hw);
		client.getOutInterceptors().add(new AuthInterceptor("admin","admin"));
		client.getOutInterceptors().add(new LoggingOutInterceptor());
		System.out.println(hw.sayHello("skymr"));

控制台输出:

九月 15, 2015 11:21:07 上午 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
INFO: Creating Service {http://impl.ws.hello.skymr.com/}helloWorldws from WSDL: http://192.168.2.102:8080/spring_cxf/doWS/HelloWorld?wsdl
--------------
九月 15, 2015 11:21:09 上午 org.apache.cxf.services.helloWorldws.HelloWorldBeanPort.HelloWorld
INFO: Outbound Message
---------------------------
ID: 1
Address: http://192.168.2.102:8080/spring_cxf/doWS/HelloWorld
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><authrity><username>admin</username><password>admin</password></authrity></soap:Header><soap:Body><ns2:sayHello xmlns:ns2="http://ws.hello.skymr.com/"><arg0>skymr</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------
你好skymr,欢迎进入Web Service学习课程

取出SOAP消息:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
	<soap:Header>
		<authrity>
			<username>admin</username>
			<password>admin</password>
		</authrity>
	</soap:Header>
	<soap:Body>
	...
	</soap:Body>
</soap:Envelope>

自定义拦截器完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值