WebService框架CXF实战一自定义拦截器(五)

CXF已经内置了一些拦截器,这些拦截器大部分默认添加到拦截器链中,有些拦截器也可以手动添加,如手动添加CXF提供的日志拦截器。也可以自定义拦截器,CXF中实现自定义拦截器很简单,只要继承AbstractPhaseInterceptor或者AbstractPhaseInterceptor的子类(如AbstractSoapInterceptor)即可。

自定义权限认证拦截器

权限认证拦截器处理SOAPHeader中的认证信息,客户端在发起请求时在SOAPHeader中添加认证信息,服务端在接收到请求后,校验认证信息,校验通过则继续执行,校验不通过则返回错误。

<!-- 认证信息格式如下 -->
<auth xmlns="http://www.tmp.com/auth">
    <name>admin</name>
    <password>admin</password>
</auth>

客户端添加授权拦截器

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;

/**
 * 添加授权拦截器
 * 用于在客户端发请求时添加授权
 * @author [email protected]
 *
 */
public class AuthAddInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
    public AuthAddInterceptor(){
        //准备发送阶段
        super(Phase.PREPARE_SEND);
    }

    @Override
    public void handleMessage(SoapMessage message) throws Fault {
        List<Header> headers = message.getHeaders();

        Document doc = DOMUtils.createDocument();

        //Element auth = doc.createElement("auth");
        Element auth = doc.createElementNS("http://www.tmp.com/auth", "auth");

        Element name = doc.createElement("name");
        name.setTextContent("admin");

        Element password = doc.createElement("password");
        password.setTextContent("admin");  

        auth.appendChild(name);
        auth.appendChild(password);

        headers.add(new Header(new QName(""), auth));
    }
}

服务端授权验证拦截器

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;

/**
 * 服务端输入拦截器
 * 拦截请求有没有授权信息
 * @author [email protected]
 *
 */
public class AuthValidateInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
    public AuthValidateInterceptor(){
        super(Phase.PRE_INVOKE);
    }

    @Override
    public void handleMessage(SoapMessage message) throws Fault {
        List<Header> headers = message.getHeaders();
        if(headers == null || headers.size() < 1) {
            throw new Fault(new Exception("无授权信息!"));
        }

        Element auth = null;
        //获取授权信息元素
        for(Header header : headers){
            QName qname = header.getName();
            String ns = qname.getNamespaceURI();
            String tagName = qname.getLocalPart();
            if(ns != null && ns.equals("http://www.tmp.com/auth") && tagName != null && tagName.equals("auth")){
                auth = (Element)header.getObject();
                break;
            }
        }

        //如果授权信息元素不存在,提示错误
        if(auth == null){
            throw new Fault(new Exception("无授权信息!"));
        }

        NodeList nameList = auth.getElementsByTagName("name");
        NodeList pwdList = auth.getElementsByTagName("password");
        if(nameList.getLength() != 1 || pwdList.getLength() != 1){
            throw new Fault(new Exception("授权信息错误!"));
        }

        String name = nameList.item(0).getTextContent();
        String password = pwdList.item(0).getTextContent();
        if(!"admin".equals(name) || !"admin".equals(password)){
            throw new Fault(new Exception("授权信息错误!"));
        }
    }
}

服务端拦截器配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:soap="http://cxf.apache.org/bindings/soap"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <jaxws:endpoint id="helloWSEndpoint" implementor="#helloWS" address="/hello">
        <jaxws:inInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
            <bean class="com.rvho.cxfserver.interceptor.AuthValidateInterceptor"></bean>
        </jaxws:inInterceptors>
        <jaxws:outInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
        </jaxws:outInterceptors>
    </jaxws:endpoint>
</beans>

客户端请求

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(HelloWS.class);
factory.setAddress("http://localhost:8280/cxfserver/services/hello");

factory.getInInterceptors().add(new org.apache.cxf.interceptor.LoggingInInterceptor());

//客户端授权拦截器
factory.getOutInterceptors().add(new com.rvho.cxfclient.interceptor.AuthAddInterceptor());
factory.getOutInterceptors().add(new org.apache.cxf.interceptor.LoggingOutInterceptor());

HelloWS helloWS = factory.create(HelloWS.class);
String welcome = helloWS.welcome("[email protected]");

CXF日志拦截器

CXF提供了输入日志拦截器LoggingInInterceptor和输出日志拦截器LoggingOutInterceptor,日志拦截器可以用在服务端也可以用在客户端。在测试或者调试的时候,可以用日志拦截器输出服务端、客户端请求和接收到的信息。

服务端日志内容

七月 30, 2015 10:51:37 上午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS
信息: Inbound Message
----------------------------
ID: 1
Address: http://localhost:8280/cxfserver/services/hello
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], cache-control=[no-cache], connection=[keep-alive], Content-Length=[212], content-type=[text/xml; charset=UTF-8], host=[localhost:8280], pragma=[no-cache], SOAPAction=[""], user-agent=[Apache CXF 3.1.1]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcome xmlns:ns2="http://www.tmp.com/services/hello"><name>[email protected]</name></ns2:welcome></soap:Body></soap:Envelope>
--------------------------------------

七月 30, 2015 10:51:37 上午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS
信息: Outbound Message
---------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcomeResponse xmlns:ns2="http://www.tmp.com/services/hello"><return>欢迎使用CXF![email protected]</return></ns2:welcomeResponse></soap:Body></soap:Envelope>
--------------------------------------

客户端日志内容

七月 30, 2015 10:51:37 上午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS
信息: Outbound Message
---------------------------
ID: 1
Address: http://localhost:8280/cxfserver/services/hello
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcome xmlns:ns2="http://www.tmp.com/services/hello"><name>[email protected]</name></ns2:welcome></soap:Body></soap:Envelope>
--------------------------------------
七月 30, 2015 10:51:37 上午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS
信息: Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {content-type=[text/xml;charset=UTF-8], Date=[Thu, 30 Jul 2015 02:51:37 GMT], Server=[Apache-Coyote/1.1], transfer-encoding=[chunked]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcomeResponse xmlns:ns2="http://www.tmp.com/services/hello"><return>欢迎使用CXF![email protected]</return></ns2:welcomeResponse></soap:Body></soap:Envelope>
--------------------------------------
欢迎使用CXF![email protected]

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 09:33:54

WebService框架CXF实战一自定义拦截器(五)的相关文章

WebService框架CXF实战一拦截器Interceptor(四)

拦截器(Interceptor)是CXF功能最主要的扩展点,可以在不对核心模块进行修改的情况下,动态添加很多功能.拦截器和JAX-WS Handler.Filter的功能类似,当服务被调用时,就会创建一个拦截器链(Interceptor Chain),拦截器链在服务输入(IN)或输出(OUT)阶段实现附加功能. 拦截器可以在客户端,也可以在服务端添加.当客户端发起一个WebService请求时,在客户端会创建输出拦截器链,服务端接收到客户端的后,会创建输入拦截器链.当服务端返回响应消息时,响应消

WebService框架CXF实战一发布RESTFul服务(七)

JAX-RS概述 JAX-RS是Java提供用于开发RESTful Web服务基于注解(annotation)的API.JAX-RS旨在定义一个统一的规范,使得Java程序员可以使用一套固定的接口来开发REST应用,避免了依赖第三方框架.同时JAX-RS使用POJO编程模型和基于注解的配置并集成JAXB,可以有效缩短REST应用的开发周期.JAX-RS只定义RESTful API,具体实现由第三方提供,如Jersey.Apache CXF等. JAX-RS包含近五十多个接口.注解和抽象类: ja

WebService框架CXF实战一传输文件(六)

CXF的文件传输通过MTOM实现.MTOM(SOAP Message Transmission Optimization Mechanism)SOAP消息传输优化机制,可以在SOAP消息中发送二进制数据.MTOM允许将消息中包含的大型数据元素外部化,并将其作为无任何特殊编码的二进制数据随消息一起传送.相对于把二进制转为base64进行传输,MTOM具有更高的传输效率. 文件传输包装类 CXF文件传输DataHandler只有二进制数据,没有文件名.文件类型和文件大小等,需要额外的传输参数.通常自

WebService框架CXF实战(一)

Apache CXF提供了用于方便地构建和开发WebService的可靠基础架构.它允许创建高性能和可扩展的服务,可以部署在Tomcat和基于Spring的轻量级容器中,也可以部署在更高级的服务器上,例如Jboss.WebSphere或WebLogic. CXF提供了以下功能: WebService服务标准支持: Java API for XML Web Services (JAX-WS) SOAP WebService描述语言(Web Services Description Language

WebService框架CXF实战一在Tomcat中发布WebService(二)

服务接口及实现类请参考WebService框架CXF实战(一) 创建Maven Web项目,在pom.xml中添加CXF和Spring Web的引用,由于CXFServlet需要Spring Web的支持. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=&quo

构建基于CXF的WebService服务(3)-- 利用拦截器实现权限验证

CXF中的拦截器分为in拦截器和out拦截器,又有客户端拦截器和服务端拦截器. 拦截器使用流程:客户端(out)-> 服务端(in)->处理业务->服务端(out)->客户端(in),并不是每一步都需要拦截器.在这里我们用到的是客户端Out拦截器和服务端in拦截器.服务端in拦截器检查用户级权限,客户端out浏览器发送用户信息给服务端. 1.创建服务端验证 JaxWsServerFactoryBean或Endpoint都可以通过getInInterceptors方法,向WebSer

Struts2自己定义拦截器实例—登陆权限验证

版本号:struts2.1.6 此实例实现功能:用户须要指定username登陆,登陆成功进入对应页面运行操作,否则返回到登陆页面进行登陆,当直接訪问操作页面(登陆后才干訪问的页面)时则不同意,须返回登陆页面. 代码例如以下: 一.页面 login.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUB

Struct2_定义拦截器并使用注解方式作用在Action的方法中

一.目的:通过在方法上加注解控制哪些方法需要登陆后才能访问 二.方式:利用拦截器判断用户是否登陆   三.实现步骤 定义配置文件struts.xml添加节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <package name="custom-default" extends="struts-default">         <interceptors>             &

力所能及之struts2 拦截器定义的包不同是不是也要在其他包定义拦截器

小狼的定义拦截器拦截非登陆用户操作,但是我的action分别在不同的package中,是不是我的拦截器必须要在每个package中都要定义呢? 可不可以定义一个公用的? 这是必须的. <package name="default" extends="struts-default" namespace="/"> <interceptors> <interceptor name="custom" cl