SOAP头鉴权的实现

       技术背景:引擎为Axis1.4,接口实现方式为wsdl文件生成服务端、客户端代码,请求消息为SOAP报文。

       为了强化SOAP服务器对请求消息合法性的校验,我们采用两种安全性保护措施:1. SOAP请求消息增加Header头域令牌,要求包含用户名和用户密码;2. 实现请求消息预处理拦截机制,对请求消息的令牌进行校验,并验证请求消息IP地址的合法性。

       为此,我们要做两件事情:一,如何将Header域加入到请求消息中,使之能够通过Axis引擎的解析;二,如何通过请求消息获得请求IP。

       关于第一点,有两种方式实现。比较简单的实现,就是在所有的请求指令中,扩展对象,存储Header对象。这种方式比较笨拙,对原请求消息Body的影响较大。另外一种就是直接在Body之外统一增加节点Header。这种方式较为灵活,对元请求消息格式没有影响。

       下面就说明实现请求Header域的操作步骤。

1.     在wsdl中定义Header域。

Header内容元素定义:
			<element name="Security">
				<complexType>
					<sequence>
						<element name="UserToken" type="wsse:UserToken" />
					</sequence>
				</complexType>
			</element>
			<complexType name="UserToken">
				<sequence>
					<element name="user" type="xsd:string" />
					<element name="pass" type="xsd:string" />
				</sequence>
			</complexType>

Header定义
<wsdl:message name="AllRequestHeader">
		<wsdl:part element="wsse:Security" name="request_header" />
	</wsdl:message>

2.     将Header合入到每个请求的Operation定义中。

增加header之前:
		<wsdl:operation name="createMyBusiness">
			<wsdlsoap:operation soapAction="" />
			<wsdl:input name="createMyBusinessRequest">
				<wsdlsoap:body use="literal" />
			</wsdl:input>
			<wsdl:output name="createMyBusinessResponse">
				<wsdlsoap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>

增加header后:
		<wsdl:operation name="createMyBusiness">
			<wsdlsoap:operation soapAction="" />
			<wsdl:input name="createMyBusinessRequest">
				<wsdlsoap:header message="impl:AllRequestHeader"
					part="request_header" use="literal" />
				<wsdlsoap:body use="literal" />
			</wsdl:input>
			<wsdl:output name="createMyBusinessResponse">
				<wsdlsoap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>

3.     使用Axis自带的WSDL2Java工具,根据修改后的wsdl生成代码。

     自此,SOAP请求消息就有了Header域,接下来的工作,就是如何拦截请求,统一校验Header和IP了。

     实现请求消息头鉴权拦截器的WSDD配置(Axis1.4):

1.     拦截校验类需要继承BasicHandler

2.     在server-config.wsdd下增加配置(请关注RequestValidate的配置):

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
	xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
	<globalConfiguration>
		<parameter name="sendMultiRefs" value="true" />
		<parameter name="disablePrettyXML" value="true" />
		<parameter name="adminPassword" value="admin" />
		<parameter name="attachments.Directory" />
		<parameter name="dotNetSoapEncFix" value="true" />
		<parameter name="enableNamespacePrefixOptimization"
			value="false" />
		<parameter name="sendXMLDeclaration" value="true" />
		<parameter name="attachments.implementation"
			value="org.apache.axis.attachments.AttachmentsImpl" />
		<parameter name="sendXsiTypes" value="true" />
		<requestFlow>
			<handler type="java:org.apache.axis.handlers.JWSHandler">
				<parameter name="scope" value="session" />
			</handler>
			<handler type="java:org.apache.axis.handlers.JWSHandler">
				<parameter name="scope" value="request" />
				<parameter name="extension" value=".jwr" />
			</handler>
		</requestFlow>
	</globalConfiguration>
	<handler name="LocalResponder"
		type="java:org.apache.axis.transport.local.LocalResponder" />
	<handler name="URLMapper"
		type="java:org.apache.axis.handlers.http.URLMapper" />
	<handler name="Authenticate"
		type="java:org.apache.axis.handlers.SimpleAuthenticationHandler" />
	<!--请求消息拦截类定义-->
	<handler name="RequestValidate"
		type="java:com.validation.RequestValidate" />
	<service name="AdminService" provider="java:MSG">
		<parameter name="allowedMethods" value="AdminService" />
		<parameter name="enableRemoteAdmin" value="false" />
		<parameter name="className" value="org.apache.axis.utils.Admin" />
		<namespace>http://xml.apache.org/axis/wsdd/</namespace>
	</service>
	<service name="Version" provider="java:RPC">
		<parameter name="allowedMethods" value="getVersion" />
		<parameter name="className" value="org.apache.axis.Version" />
	</service>

	<!-- Services from ImsService WSDL service -->
	<service name="SoapService" provider="java:RPC" style="wrapped"	use="literal">
                <!--拦截请求消息流-->
		<requestFlow>
			<handler type="RequestValidate" />
		</requestFlow>
		<!--拦截响应消息流-->
		<responseFlow>
			<handler type="RequestValidate" />
		</responseFlow>
		...<!--其它具体接口指令-->
	</service>
</deployment>
3.     RequestValidate类具体实现。

package com.validation;

import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.message.MessageElement;
import org.apache.axis.message.SOAPHeader;
import org.apache.axis.transport.http.HTTPConstants;

/**
 * 头鉴权拦截器,需要继承BasicHandler
 */
public class RequestValidate
    extends BasicHandler
{
    private static final long serialVersionUID = 1L;

    /**invoke
     * @param mc mc
     */
    public void invoke(MessageContext mc)
        throws AxisFault
    {
        //获取Header
        Message msg = mc.getRequestMessage();
        SOAPHeader header = null;
        try
        {
            header = (SOAPHeader) msg.getSOAPHeader();
        }
        catch (SOAPException e)
        {
            e.printStackTrace();
            throw new AxisFault(new QName("20000"), "Header-node error!", null, null);
        }
        List<?> list = header.getChildren();
        MessageElement token = (MessageElement) list.get(0);
        list = token.getChildren();
        MessageElement authenNode = (MessageElement) list.get(0);
        list = authenNode.getChildren();
        MessageElement nameNode = (MessageElement) list.get(0);
        String userName = nameNode.getValue();//user节点
        MessageElement pwdNode = (MessageElement) list.get(1);
        String password = pwdNode.getValue();//pass节点
        //对user和pass的校验省略
        System.out.println("user:"+userName+",pass:"+password);

        //获取SOAP请求的IP
        HttpServletRequest request =
            (HttpServletRequest) mc.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
        String ipAddr = request.getRemoteAddr();
        //对IP的校验省略
        System.out.println("requestIP:" + ipAddr);
    }
}

     至此,SOAP请求的拦截器基本实现,我们可以在请求消息的Body之上,增加Header域:

<SOAP-ENV:Header> 
	<m:Security xmlns:m="http://wsse.email.soapservice.google.com">  
		<m:UserToken> 
			<m:user>myname</m:user> 
			<m:pass>mypass</m:pass> 
		</m:UserToken> 
	</m:Security> 
</SOAP-ENV:Header>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值