文章 http://5148737.blog.51cto.com/5138737/1606499 介绍了如何将cxf与spring整合,本文将介绍如何添加拦截器,并使用权限校验的案例,来进行讲解。

    整个过程为:client端调用server端的wsdl之前,配置拦截器,先添加 权限等相关信息, 发送请求到server端, server端同样配置拦截器,校验权限信息是否正确,如果不正确,则打印异常信息。

    拦截器需要继承AbstractPhaseInterceptor 类。

(1)实现client端拦截器,添加权限信息(userId,userPass在spring配置文件中注入)

public class AddHeaderInteceptor extends AbstractPhaseInterceptor<SoapMessage>{
	private String userId;
	private String userPass;
	public AddHeaderInteceptor() {
		super(Phase.PREPARE_SEND);
	}

	@Override
	public void handleMessage(SoapMessage soapMessage) throws Fault {
		List<Header> headers = soapMessage.getHeaders();
		Document doc = DOMUtils.createDocument();
		Element userIdElement = doc.createElement("userId");
		Element userPassElement = doc.createElement("userPass");
		userIdElement.setTextContent(userId);
		userPassElement.setTextContent(userPass);
		Element authElement = doc.createElement("AuthHeader");
		authElement.appendChild(userIdElement);
		authElement.appendChild(userPassElement);
		QName qName = new QName("xiejun");
		SoapHeader soapHeader = new SoapHeader(qName, authElement);
		headers.add(soapHeader);
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public String getUserPass() {
		return userPass;
	}

	public void setUserPass(String userPass) {
		this.userPass = userPass;
	}
}

解释:首先获得了SoapMessage的header,为一个list,创建了一个AuthHeader元素,里面包含userId与userPass两个子元素,组装成SoapHeader,最后将SoapHeader添加到header list中


(2)客户端配置文件,配置该拦截器 

<!-- 注入相关权限信息 -->
<bean id="addHeaderInteceptor" class="com.xj.interceptor.AddHeaderInteceptor">
        <property name="userId" value="xiejun"/>    
        <property name="userPass" value="1234"/>
     </bean>
     
   <jaxws:client id="hello" serviceClass="com.xj.service.IHello" address="http://localhost/cxf/testHello?wsdl">
        <!--  <jaxws:inInterceptors>
              <ref bean="handlerMessage"/>
          </jaxws:inInterceptors>
         -->  
          <jaxws:outInterceptors>
              <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
              <ref bean="addHeaderInteceptor"/>
          </jaxws:outInterceptors>
   </jaxws:client>


如上所示,可以同时为in和out两个拦截器链 配置 拦截器,这里我们为out拦截器链配置,其一为cxf本身自带的日志拦截器,打印日志显示;其二为我们添加权限信息的拦截器。


至此为止,客户端配置结束


(3)实现server端拦截器,校验权限信息是否正确

public class CheckHeader extends AbstractPhaseInterceptor<SoapMessage>{

	public CheckHeader() {
		super(Phase.PRE_INVOKE);
	}

	@Override
	public void handleMessage(SoapMessage soapMessage) throws Fault {
		List<Header> headers = soapMessage.getHeaders();
		for(Header header:headers){
			SoapHeader soapHeader = (SoapHeader)header;
			Element element = (Element)soapHeader.getObject();
			if(element.getTagName().endsWith("AuthHeader")){
				NodeList userIdList = element.getElementsByTagName("userId");
				NodeList userPassList = element.getElementsByTagName("userPass");
				if(userIdList==null||userIdList.getLength()<1||userPassList==null||userPassList.getLength()<1){
					System.out.println("error2");
				}
				String username = userIdList.item(0).getTextContent();
				String password = userPassList.item(0).getTextContent();
				if(!username.equals("xiejun")||!password.equals("123456")){
					System.out.println("error3");
				}
				
			}else{
				System.out.println("error1");
			}
		}
	}
}

解释:拦截器中取出header信息,进行校验,不正确则打印异常信息,真实情况则可能是抛出异常。


(4)配置server端拦截器(与client配置相同)

<bean id="checkHeader" class="com.xj.interceptor.CheckHeader"/>
    
     <!-- <bean id="hello" class="com.xj.service.HelloImpl"/>  --> 
     <jaxws:endpoint id="testHello" implementor="com.xj.service.HelloImpl" address="/testHello" >
        <jaxws:inInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
            <ref bean="checkHeader"/>
        </jaxws:inInterceptors>
        <jaxws:outInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
        </jaxws:outInterceptors>
     </jaxws:endpoint>

这里将检验权限拦截器配置在in 拦截器链,因为在接收到请求之前,我们就要进行权限的验证。


启动该项目,发现如果用户名或密码不正确的话,则会打印错误信息。