`
huiseyiyu
  • 浏览: 102476 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

CXF 拦截器的使用(转)

 
阅读更多

CXF 拦截器的使用

    在做SP短信管理平台开发时,需要连接电信ISAG短信网关,而电信ISAG短信网关提供WebService 短信提交服务,需要开发WebService客户端连接网关。开发时使用CXF技术为开发技术。
    连接时,根据服务要求添加头信息,在头信息中增加验证信息,比如用户ID,加密密码,还有其他业务信息,类似下面的Demo代码:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header>
        <tns:RequestSOAPHeader
            xmlns:tns="http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1">
            <tns:username xmlns="http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1" >
                test_username
            </tns:username>
            <tns:password xmlns="http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1">
                b936443545b5061eceff663eadd8e91d
            </tns:password>
            <tns:timeStamp xmlns="http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1">
                1013135742
            </tns:timeStamp>
        </tns:RequestSOAPHeader>
    </soap:Header>
    <soap:Body>
        <!-- 省略 -->
    </soap:Body>
</soap:Envelope>

而SoapHeader信息使用拦截器,可以很容易添加,下面的Sample代码添加头信息:

import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.xml.namespace.QName;

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


public class SampleHeaderInterceptor extends AbstractSoapInterceptor {

    private static String namespaceURI = "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1";

    public SampleHeaderInterceptor() {
        super(Phase.WRITE);
    }

    public void handleMessage(SoapMessage message) throws Fault {

        String timeStampStr = df.format(new Date());
        String spPasswordStr = getSpPassword(System.getProperty("spId", ""), System.getProperty("spKey", "") );

        QName qName = new QName("RequestSOAPHeader");

        Document document = DOMUtils.createDocument();

        Element spId = document.createElement("tns:spId");
        spId.setTextContent(System.getProperty("spId", ""));

        Element spPassword = document.createElement("tns:spPassword");
        spPassword.setTextContent(spPasswordStr);

        Element root = document.createElementNS(namespaceURI, "tns:RequestSOAPHeader");
        root.appendChild(spId);
        root.appendChild(spPassword);

        SoapHeader header = new SoapHeader(qName, root);
        List<Header> headers = message.getHeaders();
        headers.add(header);
    }

    private static String getSpPassword(String spId, String key) {
        try {
            return MD5.md5((spId + key).getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

}

使用时,在配置文件中添加Out 拦截器,配置文件如下:
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
        <property name="serviceClass" value="sample.service.SendSms" />
         <property name="address" value="http://localhost:8080/service/sms/SendSmsService" />
         <property name="outInterceptors">
            <list>
                <bean class="sample.client.SampleSOAPHeaderInterceptor" />
            </list>
        </property>
    </bean>

也可以在代码中直接添加拦截器:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setAddress("http://localhost:8080/service/sms/SendSmsService");
        factory.setServiceClass(SendSms.class);
        factory.getOutInterceptors().add(new sample.client.SampleSOAPHeaderInterceptor());

这样就可以完成Out拦截器了。
但接下来就遇到问题了,短信上行(回复),还有状态报告返回都会添加回访用户名和密码,(类似提交短信也要进行用户名密码验证,否则我们的接收平台会收到很多可能是别人无效的信息),于是获取用户名和密码的拦截器也需要开发,但是在开发读取拦截器时都无法获取头信息,弄了快一天都行,而任务要求时间紧,到网上Google 下,使用了Handler 处理机制进行了处理,代码如下:

import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.log4j.Logger;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SampleSoapAuthHandler implements Handler<SOAPMessageContext> {

    private static Logger log = Logger.getLogger(SampleSoapAuthHandler.class);
   
    private String spRevId;
    private String spRevpassword;

    public void close(MessageContext messageContext) {
        log.info("SampleSoapAuthHandler close");
    }

    public boolean handleFault(SOAPMessageContext messageContext) {
        log.error("handleFault error");
        return false;
    }

    public boolean handleMessage(SOAPMessageContext messageContext) {
        SOAPMessage message = messageContext.getMessage();
        Boolean outboundProperty = (Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (!outboundProperty) { // InBound Message,
            String spRevId = "";
            String spRevpassword = "";
            try {
                SOAPHeader soapHeader = message.getSOAPHeader();
                NodeList nodeList = soapHeader.getChildNodes();
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Node nodeAuth = nodeList.item(i);
                    if (nodeAuth.getNodeType() == Node.ELEMENT_NODE && "SampleSOAPHeader".equals(nodeAuth.getLocalName())) {
                        for (Node node = nodeAuth.getFirstChild(); node != null; node = node.getNextSibling()) {
                            if (node.getNodeType() == Node.ELEMENT_NODE) {
                                if ("spRevId".equals(node.getLocalName()) && node.getFirstChild() != null) {
                                    spRevId = node.getFirstChild().getTextContent();
                                } else if ("spRevpassword".equals(node.getLocalName()) && node.getFirstChild() != null) {
                                    spRevpassword = node.getFirstChild().getTextContent();
                                }
                            }
                        }
                    }
                }

                boolean ret = validUserAndPswd(spRevId, spRevpassword);
                if (!ret) {
                    log.warn("错误的反调用户名和密码,spRevId:" + spRevId + ",spRevPassword:" + spRevpassword);
                    return ret;
                }
                log.info("收到信息,验证通过");
                System.setProperty("mo:linkId", linkId);
                return ret;

            } catch (SOAPException e) {
                log.error("解析异常,SOAPException:" + e, e);
            }
        }
        return false;
    }
   
    private boolean validUserAndPswd(String spRevId, String spRevpassword) {
        if(this.spRevId == null && this.spRevpassword == null)
            return true;
        if(this.spRevId == null && this.spRevpassword != null)
            return this.spRevpassword.equals(spRevpassword);
        if(this.spRevId != null && this.spRevpassword == null)
            return this.spRevId.equals(spRevId);
        return this.spRevId.equals(spRevId) && this.spRevpassword.equals(spRevpassword);
       
    }

    public void setSpRevId(String spRevId) {
        this.spRevId = spRevId;
    }

    public void setSpRevpassword(String spRevpassword) {
        this.spRevpassword = spRevpassword;
    }

   
}

上述代码部分来自google 搜索到的,在此谢谢原作者。

添加处理器配置文件:
<bean id="isagReceiver" class="sample.SampleReceiver" singleton="false" >
        <property name="address" value="http://localhost:8080/service/MessageService" />
        <property name="handlers">
            <list>
                <ref bean="authHandler"/>
            </list>
        </property>
    </bean>
   
    <bean id="authHandler" class="sample.SampleSoapAuthHandler" singleton="true">
        <property name="spRevId" value="username"></property>
        <property name="spRevpassword" value="pawd"></property>
    </bean>
因为自定义的处理器实现Handler接口,所以代码中只需要把自己的业务处理放在handler方法中即可,处理器链会自动调用。
终于可以完成任务了。

之后,有了空闲时间,对cxf的拦截器还是决定各种方式进行测试,今天终于得到满意的结果,把拦截验证的拦截器代码贴出来,如果有更好的建议,可以交流下:

import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SpInfoInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
    private SAAJInInterceptor inInterceptor = new SAAJInInterceptor();

    public SampleInterceptor() {
        super(Phase.PRE_PROTOCOL);
        getAfter().add(SAAJInInterceptor.class.getName()); //这一步好像是必须的,与 inInterceptor.handleMessage(message); 关联
    }

    public void handleMessage(SoapMessage message) throws Fault {
        //此处注意 是javax.xml.soap.SOAPMessage 而不是 org.apache.cxf.binding.soap.SoapMessage
        //虽然方法参数是SoapMessage
        SOAPMessage sm = message.getContent(SOAPMessage.class);
        if (sm == null) {
            inInterceptor.handleMessage(message);
            sm = message.getContent(SOAPMessage.class);
        }
        SOAPHeader header = null;
        try {
            header = sm.getSOAPHeader();
        } catch (SOAPException e) {
            e.printStackTrace();
        }
        if (header == null) {
            return;
        }

        //获取<soap:Header ..><tns:RequestSOAPHeader ...> ... </tns:RequestSOAPHeader></soap:Header>中指定的标签的内容
        NodeList nodeList = header.getElementsByTagName("tns:RequestSOAPHeader");
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node nodeAuth = nodeList.item(i);
            for (Node node = nodeAuth.getFirstChild(); node != null; node = node.getNextSibling()) {
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    //if("username".equals(node.getLocalName()) && node.getFirstChild() != null) {
                    //        username = node.getFirstChild().getTextContent(); //获取<soap:Header> 中的username参数的值
                    //}
                    if (node.getLocalName() != null && node.getFirstChild() != null)
                        System.out.println(node.getLocalName() + " <===========> " + node.getFirstChild().getTextContent());
                }
            }
            //}
        }
    }

}

上述部分代码也是参考网上代码,谢谢原作者。
代码中省略的日志信息的输出,可以自行添加。

至此, cxf 添加头信息和验证信息的两种拦截器都完成了,其他类似的功能的拦截器可以相互参考,其他的如附件的拦截器有空再补充了,今天就写到这里。

文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/java/javajs/20100106/186733.html

分享到:
评论
1 楼 wangyudong 2017-11-27  
由CXF实现的微服务需要有比较好的工具去测试RESTful API,很多REST Client是不支持自动化测试RESTful API,也不支持自动生成API文档.
之前习惯用一款名字为 WisdomTool REST Client,支持自动化测试RESTful API,输出精美的测试报告,并且自动生成精美的RESTful API文档。
轻量级的工具,功能却很精悍哦!

https://github.com/wisdomtool/rest-client

Most of REST Client tools do not support automated testing.

Once used a tool called WisdomTool REST Client supports automated testing, output exquisite report, and automatically generating RESTful API document.

Lightweight tool with very powerful features!

https://github.com/wisdomtool/rest-client

相关推荐

    CXF拦截器(Interceptor)的使用

    标题:“CXF拦截器(Interceptor)的使用” 描述:“讲解了cxf实现拦截器的原因、核心API及使用方法” 在深入探讨CXF拦截器的使用之前,我们首先需要理解其在CXF框架中的核心作用与价值。Apache CXF是一个开源框架,...

    CXF3.0+Spring3.2 自定义拦截器

    1. **CXF拦截器基础**:CXF的拦截器是基于JAX-WS规范的Handler Chain模型,分为In-bound(请求进来时触发)和Out-bound(响应出去时触发)两类。拦截器可以通过在服务配置中指定,或者通过编程方式动态添加。 2. **...

    08.CXF拦截器的理论以及如何为CXF的客户端和服务器端添加拦截器

    **CXF拦截器理论与应用** 在Web服务领域,Apache CXF是一个强大的开源框架,它提供了构建和消费SOAP和RESTful服务的能力。拦截器是CXF框架中的一个重要组成部分,允许开发者在服务调用的生命周期中插入自定义逻辑,...

    CXF使用EndpointImpl发布WebService加入拦截器

    在Java世界中,Apache CXF是一个广泛使用的开源框架,它允许开发者创建和消费Web服务。在Web服务开发中,拦截器扮演着至关重要的角色,...总的来说,理解并熟练运用CXF拦截器对于任何CXF开发者来说都是一项重要的技能。

    Cxf拦截器实例

    通过学习和理解这些示例,开发者可以更好地利用CXF拦截器来扩展和定制自己的Web服务,提高应用程序的灵活性和可维护性。无论是客户端还是服务器端,拦截器都是一个强大的工具,能够帮助我们控制和优化服务通信的每个...

    CXF WebService带有拦截器

    本篇文章将深入探讨如何使用CXF来开发具有权限控制功能的Web Service,并通过拦截器实现这一目标。 首先,我们需要理解Web Service拦截器的概念。在CXF中,拦截器是处理消息生命周期中的关键组件,它们可以在消息...

    CXF发布WebService加入拦截器

    CXF拦截器是一种AOP(面向切面编程)的概念,它们是执行特定任务的独立单元,可以在消息传递的生命周期中不同阶段被调用。拦截器可以用来处理如认证、授权、日志记录、性能监控、数据转换等任务,增强了服务的功能和...

    webservice的cxf框架拦截器demo

    本篇将深入探讨CXF框架中的拦截器(Interceptor)及其在"webservice的cxf框架拦截器demo"中的应用。 拦截器在CXF中是一种强大的工具,它允许开发者在消息发送或接收的过程中插入自定义的行为。这在处理认证、日志...

    spring集成cxf客户端和服务器端demo(含自定义拦截器)

    在本项目中,"spring集成cxf客户端和服务器端demo(含自定义拦截器)"是一个实战案例,展示了如何在Spring框架下与Apache CXF服务进行整合,实现客户端和服务端的交互,并利用拦截器来增强功能。以下是这个项目涉及的...

    10.为CXF服务器端添加自定义拦截器进行权限检查

    在开发基于CXF的Web服务时,为了确保系统的安全性和数据的完整性,通常需要对请求进行权限检查。本文将深入探讨如何为CXF服务器...在学习和应用这些知识时,结合实际案例和实践操作将有助于更好地掌握CXF拦截器的使用。

    11.为CXF客户端添加自定义拦截器完成权限控制

    在IT行业中,尤其是在服务端开发领域,Web Service是一种...总之,通过使用CXF客户端拦截器,我们可以实现细粒度的权限控制,提高系统的安全性。理解并熟练掌握这一技术,对于开发高质量、安全的服务端应用至关重要。

    webservice的cxf框架拦截器demo.rar

    这部分可能包含了客户端的代码,展示了如何在CXF客户端使用拦截器。客户端拦截器可以用来处理请求的构建和响应的解析,例如,添加身份验证信息或者对返回的数据进行解密。 5. **“1.rtf”**: 这可能是一个RTF...

    CXF-拦截器-权限控制-登录校验

    本文将深入探讨"CXF拦截器-权限控制-登录校验"这一主题。 首先,我们需要了解什么是拦截器。在CXF框架中,拦截器是实现业务逻辑和基础架构之间解耦的一种方式。它们可以插入到服务调用的生命周期中,在消息发送前或...

    13.为CXF与Spring整合发布WebService添加拦截器进行权限控制

    在Spring框架中,我们可以使用Spring的`@Bean`注解来配置CXF拦截器。首先,我们需要创建一个实现了`org.apache.cxf.interceptor.Fault`和`org.apache.cxf.phase.PhaseInterceptor`接口的类。这个类通常会包含处理...

    ip黑白名单拦截器java示例

    在IT安全领域,IP黑白名单拦截器是一种常见的技术手段,用于增强网络安全,防止恶意或不受信任的IP地址访问系统资源。以下将详细讲解基于Java实现的IP黑白名单拦截器及其核心概念。 首先,我们来看标题提及的“ip...

    CXF3.1.16 +Spring4 +MyBatis + Maven自定义拦截器 WebService实例源码下载

    "CXF3.1.16 +Spring4 +MyBatis + Maven自定义拦截器 WebService实例源码下载" 这个标题揭示了该项目的核心技术栈,包括: 1. CXF 3.1.16:这是一个开源的服务框架,用于构建和开发服务,支持SOAP和RESTful Web服务...

    CXF和Spring整合,并且添加拦截器

    **标题:“CXF和Spring整合,并且添加拦截器...拦截器的使用则允许我们在服务调用过程中插入自定义的行为,如日志记录、性能监控等。对于开发和维护复杂的分布式系统来说,这种集成方式提供了很大的灵活性和可扩展性。

    cxfSecurity.rar cxf加密 加拦截器

    【标题】"cxfSecurity.rar" 是一个与Apache CXF框架相关的压缩文件,它涉及到在Web服务(Webservice)环境中实现安全加密以及使用拦截器(Interceptors)的技术。Apache CXF是一个开源的服务框架,用于构建和开发...

    WebService之自定义拦截器(server+client)

    在IT行业中,Web服务是应用程序之间进行通信的一种标准方法,而WebService之自定义拦截器的实现,无论是...通过理解并熟练掌握CXF框架下的拦截器使用,开发者可以更好地驾驭Web服务,实现更高效、更安全的应用程序。

    CXF自定义拦截器实现安全机制实例工程

    CXF 自定义拦截器实现的 webservice安全机制实例工程, 带jar包 ,代码注释详细 内有说明文档, 由于资源过大 ,所以客户端jar包 删除掉了, 只需要把服务端的jar 拷贝到 客户端即可 , 小弟刚刚研究完 CXF 安全 。...

Global site tag (gtag.js) - Google Analytics