(六)CXF之自定义拦截器

一、需求分析

  • 客户端在调用服务端的方法时,需要进行用户名和密码验证。此时分为:
  1. 客户端请求的时候,要发送用户名密码到服务端
  2. 服务端检验用户名密码。

二、案例

  • 前提:本章案例是基于前一章节的例子进一步讲解自定义拦截器

  2.1  服务端

  • 发布服务
ublic class PublishMain {
    public static void main(String[] args) {
        
        String address="http://localhost:3333/login";
        JaxWsServerFactoryBean factoryBean=new JaxWsServerFactoryBean();
        factoryBean.setAddress(address);
        factoryBean.setServiceClass(ILogin.class);
        factoryBean.setServiceBean(new Login());
        /**
         * // 添加in拦截器 日志拦截器
         * // 添加out拦截器 日志拦截器
         */
        factoryBean.getInInterceptors().add(new LoggingInInterceptor());// 添加in拦截器 日志拦截器
        factoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); 添加out拦截器 日志拦截器
        /**
         * 添加自定义拦截器,验证客户端发送的用户名和密码
         */
        factoryBean.getInInterceptors().add(new MyLoginInteceptor());
        
        factoryBean.create();
        System.out.println("服务发布.......");
        
    }
}
  • factoryBean.getInInterceptors().add(new MyLoginInteceptor());   在接收SOAP消息的时候,会执行LoggingInInterceptor日志拦截器和

    自定义的 MyLoginInteceptor拦截器,该拦截器用于验证soap消息中的用户名和密码的合法性。

  • 编写自定义的拦截器类

package com.shyroke.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.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 MyLoginInteceptor extends AbstractPhaseInterceptor<SoapMessage> {

    public MyLoginInteceptor() {
        /**
         * Phase.PRE_INVOKE 在调用方法之前调用自定拦截器
         */
        super(Phase.PRE_INVOKE);     }

    @SuppressWarnings("null")
    public void handleMessage(SoapMessage message) throws Fault {

        List<Header> headers = message.getHeaders();
        if (headers == null && headers.size() == 0) {
            throw new Fault(new IllegalArgumentException("没有Header,拦截器实施拦截"));
        }

        Header header = headers.get(0);

        Element ele = (Element) header.getObject();
        NodeList uList = ele.getElementsByTagName("userName");
        NodeList pList = ele.getElementsByTagName("passWord");

        if (uList.getLength() != 1) {
            throw new Fault(new IllegalArgumentException("用户名格式不对"));
        }
        if (pList.getLength() != 1) {
            throw new Fault(new IllegalArgumentException("密码格式不对"));
        }

        String userName = uList.item(0).getTextContent();
        String passWord = pList.item(0).getTextContent();

        if (!userName.equals("admin") || !passWord.equals("123")) {
            throw new Fault(new IllegalArgumentException("用户名或者密码错误!"));
        }

    }

}
  • 其他代码与上一章节相同,本文省略。

  2.2  客户端

  • client.java
package com.shyroke.service;

import java.util.List;

import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;

import com.shyroke.interceptor.MyHeaderInterceptor;

public class Client {
    public static void main(String[] args) {
        ILogin login=new ILoginService().getILoginPort();
        
        org.apache.cxf.endpoint.Client client=ClientProxy.getClient(login);
        
        /**
         * LoggingInInterceptor该拦截器类会在客户端被调用前打印日志
         * LoggingOutInterceptor该拦截器类会在客户端被调用后打印日志
         */
        client.getInInterceptors().add(new LoggingInInterceptor());
        client.getOutInterceptors().add(new LoggingOutInterceptor());
        
        /**
         * 客户端请求服务端的方法的时候要先加用户名密码以供服务端验证
         */
        client.getOutInterceptors().add(new MyHeaderInterceptor("admin1","123"));
        
        MyRoleArray roles=login.getRoles();
        List<MyRole> roleList= roles.item;
        for(MyRole role:roleList) {
            System.out.println(role.getKey());
            for(Role r:role.getValue()) {
                System.out.println(r.getId()+"	"+r.getRoleName());
            }
            System.out.println("------------------");
        }
    }
}
  • client.getOutInterceptors().add(new MyHeaderInterceptor("admin1","123"))  客户端在请求服务单的方法时,会发送SOAP消息,就会先执行MyHeaderInterceptor

日志拦截器和自定义拦截器MyHeaderInterceptor,该拦截器用于发送在发送的SOAP消息中添加用户名密码等验证信息,以供服务端接收并验证。

  • MyHeaderInterceptor.java
package com.shyroke.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 MyHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    private String userName;
    private String passWord;

    public MyHeaderInterceptor(String userName, String passWord) {
        /**
         * Phase.PREPARE_SEND 准备发送SOAP消息的时候调用拦截器
         */
        super(Phase.PREPARE_SEND);
        this.userName = userName;
        this.passWord = passWord;
    }

    public void handleMessage(SoapMessage message) throws Fault {

        List<Header> headerList = message.getHeaders();

        Document doc = DOMUtils.createDocument();
        Element ele = doc.createElement("LoginHeader");
        Element uElement = doc.createElement("userName");
        uElement.setTextContent(userName);

        Element pElement = doc.createElement("passWord");
        pElement.setTextContent(passWord);

        ele.appendChild(uElement);
        ele.appendChild(pElement);

        headerList.add(new Header(new QName("http://com.shyroke"), ele));

    }

}
  • 结果:

  • 可知,服务端拦截器是生效的。

服务端代码在: 点击

客户端代码在: 点击

原文地址:https://www.cnblogs.com/shyroke/p/7966575.html