在我们当前的
SaaS
系统中
request
和
response
的验证包括两部分,一部分为
jaxb
的
schema
验证,一部分为局部业务规则约束的验证(通过在
service
实现中侵入代码进行验证)。
我一直觉得当前的验证(非数据库相关)不是很灵活,因此我就做了一个动态的验证框架,实现思路如下:
在我们的系统中每一个
service
对应多个
operation
,每一个
operation
既是一个
request/response
处理者。我们的验证是针对
request/response
,因此需要建表结构(示意)如下:
Vaidations
OperationID
|
操作
id
|
Type
|
类型
request/response
|
ValidateKey
|
验证的
key
,即
request/response
的
xpath
路径
|
ValidateRule
|
匹配
validateKey
的值
de
验证规则,利用正则表达式
|
所有的验证规则都会进行缓存以减少数据库操作。
在服务管理界面上可以动态的增加
/
删除
/
修改验证规则,在服务的调用时增加
SoapHandler
,执行过程如下:
1.
从
SOAPMessageContext
中获取请求
URL
,通过
URL
获取
OperationID
。
2.
根据
operationID
从缓存中获取请求或响应对应的所有验证规则。
3.
循环验证开始
4.
根据
ValidateKey
从
SOAPMessageContext
中获取请求
/
响应中对应的值。
5.
匹配
ValidateRule
对应的正则表达式,如果不匹配,则
fail-fast
直接抛出运行时异常;匹配则验证下一个。
6.
循环验证结束。
数据操作以及正则表达式验证大家可以自己实现,下面简单写了一个
handler
,只是为了验证通过
xpath
获取
soap request
中的
value
,如果有兴趣大家可以自己完善。
package com.hp.test.cxf.handlers;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.xml.sax.InputSource;
public class ValidationHandler implements SOAPHandler<SOAPMessageContext> {
public Set<QName> getHeaders() {
// TODO Auto-generated method stub
return null;
}
public void close(MessageContext arg0) {
// TODO Auto-generated method stub
}
public boolean handleFault(SOAPMessageContext arg0) {
// TODO Auto-generated method stub
return false;
}
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean)smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
//System.out.println("Out:"+smc.toString());
return true;
} else {
try{
//从缓存中获取此URL(operation)对应的所有验证规则
//循环验证key-rule
SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
nsContext.setNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/"); // instead of "SOAP-ENV"
nsContext.setNamespace("cxf", "http://cxf.test.hp.com/");
String name = getDataXpath(smc.getMessage(),
"/soapenv:Envelope/soapenv:Body/cxf:Person/name/child::text()",
nsContext);
//if(!name.matchs(rule)){throw new RuntimeException("name is invalid!");}
//循环结束
}catch(Exception e){e.printStackTrace();}
return true;
}
}
public String getDataXpath( SOAPMessage message, String expression, NamespaceContext nsContext )
throws java.io.IOException, javax.xml.soap.SOAPException, javax.xml.xpath.XPathExpressionException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
message.writeTo(out);
InputSource inputSource = new InputSource(
new ByteArrayInputStream(out.toByteArray())
);
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
if (nsContext != null) xPath.setNamespaceContext( nsContext );
XPathExpression xpathExpression = xPath.compile( expression );
return xpathExpression.evaluate( inputSource );
}
}
class SimpleNamespaceContext implements NamespaceContext {
private Map<String,String> map;
public SimpleNamespaceContext() {
map = new HashMap<String,String>();
}
public void setNamespace(
String prefix,
String namespaceURI
){ map.put(prefix, namespaceURI); }
// !!! doesn't fully implement getNamespaceURI API spec !!!
public String getNamespaceURI(
String prefix
){ return map.get(prefix); }
// !!! doesn't fully implement getPrefix API spec !!!
public String getPrefix( String namespaceURI ){
SinglePrefixCollector collector = new SinglePrefixCollector();
collectPrefixes( namespaceURI, collector );
return collector.getResult();
}
// !!! doesn't fully implement getPrefixes API spec !!!
public Iterator getPrefixes( String namespaceURI ){
MultiPrefixCollector collector = new MultiPrefixCollector();
collectPrefixes( namespaceURI, collector );
return collector.getResult();
}
protected void collectPrefixes( String namespaceURI, PrefixCollector collector ) {
Iterator<String> iterator = map.keySet().iterator();
while( iterator.hasNext() ) {
String prefix = iterator.next();
if ( getNamespaceURI(prefix).equals(namespaceURI) ) {
boolean addMore = collector.addPrefix(prefix);
if(! addMore ) break;
}
}
}
protected interface PrefixCollector {
// template method for subclasses
// return: true - continue collecting; false - stop collecting.
boolean addPrefix(String prefix);
}
static protected class SinglePrefixCollector implements PrefixCollector {
private String prefix = null;
// returns false to stop further additions as it can only hold one prefix
public boolean addPrefix( String prefix ) { this.prefix = prefix; return false; }
public String getResult(){ return prefix; }
}
static protected class MultiPrefixCollector implements PrefixCollector {
private List<String> prefixes = new ArrayList<String>();
// returns true as it can hold more than one prefix
public boolean addPrefix( String prefix ) { prefixes.add(prefix); return true; }
public Iterator getResult() { return prefixes.iterator(); }
}
}
请求的
wsdl
如下
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cxf="http://cxf.test.hp.com/">
<soapenv:Header/>
<soapenv:Body>
<cxf:Person>
<name>1</name>
<address>2</address>
<phone>3</phone>
<email>eddis</email>
<addresslist>
<address>
<address>8</address>
<test>9</test>
</address>
</addresslist>
</cxf:Person>
</soapenv:Body>
</soapenv:Envelope>
分享到:
相关推荐
当涉及到Web Service客户端与服务器之间的交互时,有时需要在SOAP消息中添加额外的信息,例如身份验证或安全凭证,这就是SOAP Header的作用。SOAP Header是SOAP Envelope的一部分,它允许扩展和自定义消息处理。 在...
为了实现这种验证机制,开发人员可能需要熟悉WSDL(Web Service Description Language)文件,它定义了Web服务的接口和消息结构,包括SOAP Header的使用。此外,了解SOAP协议、XML和可能的安全框架(如WS-Security)...
总之,《C++ Builder 6 SOAP Web Service》配套光盘为读者提供了一套完整的SOAP Web服务开发资源,无论你是初学者还是有经验的开发者,都能从中受益,提升你的C++ Builder 6和SOAP技术能力。通过实践书中的示例和...
`Demo XML Web Service for Windows Authentication`这个项目展示了如何配置和使用SOAP Header进行Windows身份验证。这涉及到在SOAP请求中包含特定的认证头信息,以便服务器能够验证客户端的身份。 2. **自定义身份...
【标题】"用SOAP标题验证的WEB服务"涉及到的核心概念是Web服务安全性和SOAP消息头的应用,这在C#高级编程中是一个重要的实践案例。Web服务是一种通过互联网进行通信的应用程序接口,允许不同系统间的数据交换。在此...
Web服务(Web Service)是一种基于互联网的、采用标准的XML(Extensible Markup Language)格式来交换数据的应用程序间通信方式。SOAP(Simple Object Access Protocol)是Web服务中最常见的一种消息协议,它允许...
Web服务则是一种通过网络提供可重用功能的软件系统,通常使用SOAP作为消息传递机制。 在SOAP/Web服务客户端开发中,有几个关键知识点需要理解: 1. **SOAP消息结构**:SOAP消息由三个主要部分组成:Envelope、...
基于SOAP消息组合变异的Web服务漏洞测试方法通过引入组合变异和特定的测试策略,为Web服务提供了一种更为全面和有效的漏洞检测手段。这种测试方法不仅可以提高测试的覆盖率,还能帮助开发者更快地识别和修复潜在的...
总之,SOAP Web Service作为一种成熟且广泛采用的分布式应用程序模型,为企业和个人提供了高效、灵活的服务交互方式。随着技术的不断发展,尽管出现了RESTful API等新的服务架构,SOAP Web Service仍然在许多领域...
数据绑定是Web Service中的一个重要概念,它涉及到将XML消息转换为编程语言中的对象,反之亦然。WS-Security提供了Web Service的安全框架,确保数据在传输过程中的安全性。WS-Notification用于服务间的事件通知,而...
在本文中,我们将探讨一种基于Web Service的身份验证方法,这种方法是通过SOAP Header来实现的。SOAP Header是一种在SOAP消息中包含附加信息的方式,可以用来传递安全、事务处理、路由等元数据。以下是对该主题的...
SOAP 消息遵循一定的语法规则,如消息必须用 XML 编码,使用 SOAP Envelope 命名空间,并且不能包含 DTD 引用和 XML 处理指令。以下是一个基本的 SOAP 消息示例: ```xml <soap:Envelope xmlns:soap=...
6. **安全考虑**:Web Service的安全性是至关重要的,可以通过配置服务来实现基本的身份验证、消息认证、数据加密等。例如,使用WS-Security标准可以添加用户名令牌、数字签名和加密。 7. **高级特性**:除了基本的...
相比之下,SOAP服务的安全控制通常涉及更复杂的XML消息验证和处理,因为所有的业务逻辑和安全信息都封装在SOAP消息中。这可能导致在现有的HTTP代理服务器上实现安全策略时遇到困难,因为代理可能无法直接解析和处理...
Spring-WS 是一个基于 Java 的轻量级 Web Service 框架,专注于 SOAP 协议。这个框架使得开发者能够创建符合 W3C 标准的、契约优先的 Web Service 应用程序。在本篇文章中,我们将深入探讨如何使用 Spring-WS 实现 ...
XML Web Service的安全性是关键问题,常见的安全措施包括SSL/TLS加密、WS-Security(Web Services Security)提供消息级安全,以及身份验证和授权机制。 七、Web Service的集成 Web Service常被用于系统集成,例如...
首先,开发者创建一个BizTalk项目,定义需要暴露为Web服务的操作和消息类型。然后,使用BizTalk Orchestrator设计业务流程,将这些操作串联起来。一旦设计完成,可以通过BizTalk Administrator将编排部署到BizTalk...
在服务类中,定义公共方法作为服务操作,这些方法将暴露为Web Service的方法供客户端调用。 2. **定义服务接口**: WSDL文件描述了Web Service的接口,包括服务地址、操作、输入/输出消息等。在ASMX中,编译后的...
在Java中,你可以使用JAX-WS(Java API for XML Web Services)来处理SOAP消息头。以下是一个简单的示例: 1. **创建消息监听器**: ```java import javax.xml.ws.handler.MessageContext; import javax.xml.ws....