• (六)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));
    
        }
    
    }
    • 结果:

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

    服务端代码在: 点击

    客户端代码在: 点击

  • 相关阅读:
    php 数组分页
    Fchart
    thinkphp对数据库操作有哪些内置函数
    MySQL性能优化的最佳20+条经验
    apache 简单笔记
    PHPMyadmin 配置文件详解(配置)
    mysql 常用知识
    分布式微服务日志的配置
    分布式微服务的配置
    分布式接口的调用
  • 原文地址:https://www.cnblogs.com/shyroke/p/7966575.html
Copyright © 2020-2023  润新知