CXF-08:自定义CXF拦截器来进行权限控制

本文介绍了如何在CXF服务端和客户端使用自定义拦截器进行权限控制。通过修改In拦截器处理服务器端的身份验证,以及Out拦截器在客户端添加Header信息。实现了只有提供正确用户名和密码的情况下才能调用Web Service的功能。
摘要由CSDN通过智能技术生成
自定义拦截器:
需要实现Interceptor接口,实际上,我们一般会继承AbstractPhaseInterceptor;
做一个权限控制,有用户名和密码的时候才允许调用 Web Service:

         * 1 . 在服务器端将系统提供的In拦截器改为自定义拦截器

                 在运行起来的CXF服务端不需要做任何的改动,只需要修改In拦截器:

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.xml.ws.Endpoint;
import org.fjava.cxf.ws.HelloWorld;
import org.fjava.cxf.ws.auth.AuthInterceptor;
import org.fjava.cxf.ws.impl.HelloWorldWs;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;
//发布Web Service
public class ServiceMain {
	public static void main(String[] args) throws IOException{
		HelloWorld hw = new HelloWorldWs();
		//调用Endpoint的publish("本机地址","服务的提供者:一个Web Service对象")方法发布Web Service
		EndpointImpl ep = (EndpointImpl) Endpoint.publish("http://192.168.0.159:6786/sayHello", hw);
		//添加In拦截器,该AuthInterceptor负责检查用户名、密码是否正确
		ep.getInInterceptors().add(new AuthInterceptor());
		System.out.println("Web Service暴露成功!");
		//暴露成功后可以被任何平台的任何语言调用
		//检查调用地址http://192.168.*.*/sayHello?wsdl
	}
}
                 增加你自己写的AuthInterceptor拦截器继承AbstractPhaseInterceptor:
import java.util.ArrayList;
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;
//通过PhaseInterceptor,可以指定拦截器在哪个阶段起作用。
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
	public AuthInterceptor(){
		//super表示显示调用父类有参数的构造器。
		//显示调用父类构造器,程序将不会隐式调用父类无参的构造器。
		//---父类构造器里方法AbstractPhaseInterceptor(String phase)
		//---phase是指一个拦截阶段
		//---CXF文档里有Phase类,这个类里有各个阶段
		super(Phase.PRE_INVOKE);//该拦截器将会在"调用之前"拦截Soap消息。
	}
	//实现自己的拦截器时,需要实现handleMessage方法。
	//handleMessage方法中的形参就是被拦截到的Soap消息。
	//一旦程序获得了Soap消息,剩下的事情就可以解析Soap消息,或修改Soap消息。  
	@Override
	public void handleMessage(SoapMessage msg) throws Fault{
		//下面代码显示"调用之前"成功拦截了信息
		System.out.println("----------------"+ msg);
		//得到Soap消息的所有Header
		List<Header> headers = new ArrayList<Header>();
		try {
			headers = msg.getHeaders();
		} catch (Exception e) {
			throw new Fault(new IllegalArgumentException("没有Header,禁止调用!"));
		}
		//如果根本没有Header
		if(headers == null || headers.size() < 1 ){
			throw new Fault(new IllegalArgumentException("没有Header,禁止调用!"));
		}
		System.out.println("headers" + headers);
		//假如要求第一个Header携带了用户名、密码信息
		Header firstHeader = headers.get(0);
		Element ele = (Element)firstHeader.getObject();
		NodeList userIds = ele.getElementsByTagName("userId");
		NodeList passwords = ele.getElementsByTagName("password");
		if(userIds == null || userIds.getLength() != 1){
			throw new Fault(new IllegalArgumentException("用户名格式不正确!"));
		}
		if(passwords == null || passwords.getLength() != 1){
			throw new Fault(new IllegalArgumentException("密码格式不正确!"));
		}
		System.out.println("userIds" + userIds);
		System.out.println("passwords" + passwords);
		//得到userId元素里的文本内容,以该内容作为用户名
		String userId = userIds.item(0).getTextContent();
		String password = passwords.item(0).getTextContent();
		//实际项目中,是去查询数据库,该用户名、密码是否被授权访问该Web Service。
		if(!"admin".equals(userId) && !"admin".equals(password)){
			throw new Fault(new IllegalArgumentException("用户名、密码不正确!"));
		}
	}
}

           若不写客户端拦截器则会报错:没有用户名与密码无法正常调用该接口(用户名、密码填写错误也会报错)

服务端输出:

十月 24, 2016 10:53:45 下午 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
信息: Creating Service {http://impl.ws.cxf.fjava.org/}HelloWorldWs from class org.fjava.cxf.ws.HelloWorld
十月 24, 2016 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值