站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题企业应用的Web服务安全技术, 第2部分:框架

企业应用的Web服务安全技术, 第2部分:框架

摘要: 企业应用的Web服务安全技术, 第2部分:框架
内容:
企业应用的Web服务安全技术, 第2部分:框架

作者:Denis Piliptchouk

译者:v_gyc


版权声明:任何获得Matrix授权的网站,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
作者:Denis Piliptchouk;v_gyc
原文地址: http://www.onjava.com/pub/a/onjava/2005/03/30/wssecurity2.html
中文地址:http://www.matrix.org.cn/resource/article/43/43900_WS-Security_Framework.html
关键词: WS-Security Framework

本文是讨论如何在企业环境中实现和应用基于Web服务安全技术的安全保护方案系列文章的第2部分。在本系列的第1部分中回顾了现有的解决方案及其缺陷,并提出开发一个新的Web服务安全工具包的方案,此工具包可以解决其中部分缺陷(见第一部分)。本文将进一步介绍此Web服务安全工具包的框架(下载部分源代码),并解释工具包内Web服务安全的特性与Java语言的面向对象特性之间的高层抽象映射关系。

客户端
第一部分中工具包需求部分指出, 开发工具包的目的之一是简化客户在当前的开发环境下处理Web服务安全的工作。这些工作应该移至框架层, 以便框架层最终将这些工作代理到底层基础设施——真正应该处理这些工作的地方。 因此,在讨论工具包的结构以及工具包内实体与WSSE相关标准之间的关系前, 让我们将工具包视为一个黑盒子, 从客户的角度来体验一下(如何使用工具包)。

WsseHeaderToken wsseHeader = new WsseHeaderToken();

// Add Timestamp element to the WSSE Header 添加时间戳元素
TsToken ts = wsseHeader.AddTimestamp(60);

// Sign the timestamp element with default certificate使用缺省证书对时间戳元素签名
WsToken[] sigTokens = new WsToken[] {ts};
wsseHeader.AddSignature(sigTokens);

// Encrypt the signature and body elements with default key 使用缺省的密钥加密签名及主体中元素
WsTokenRef[] encTokens = new WsTokenRef[]
{ new DSigTokenRef(), new SoapBodyRef() };
wsseHeader.AddEncryption(encTokens);

wsseHeader.ProcessHeader();

Element soap = wsseHeader.GetSoapEnvelope();


这个简单示例构造了一个包含时间戳子元素的Web服务安全(以下简记为WSSE)头部元素, 并从配置文件中获取XML签名提供者的信息, 使用相应XML签名提供者工具对时间戳元素签名, 进而使用配置的XML加密提供者对安全头部中的签名元素和时间戳元素进行加密。

XML文件解析具有过程化的本质, 这将带来处理WSSE XML信息的困难, 导致混乱复杂相互纠缠的代码。 工具包中实现了复杂安全规范的代码, 试图将安全领域的过程化规则映射到面向对象领域的对应部分。 包中代表WSSE元素的类, 隔离了XML解析过程, 创建了处理XML代码的面向对象的包装器。

工具包提供的WsseHeaderToken类, 对一些功能进行了便于使用的封装, 这样可以使得客户与框架的复杂性隔离。 如果有必要, 客户也可以在代码内直接创建和访问工具包内的其他类。 例如, 当现有帮助类未提供处理某种类型的元素的功能时, 可以创建相应的处理器对象进行处理, 并将处理结果添加到头部安全信息中。 在下面代码中使用一个示例处理器和示例标记, 演示了如何从WSSE信息头部拷贝标记元素到另一个WSSE信息头部

// Reference and read WSSE header with null actor 
使用null操作器引用和读取WSSE 头部
WsseHeaderRef ref = WsseHeaderRef.CreateFromFile(filename, null);
WsseHeaderToken wsseHeader = ref.GetWsseHeader();

// Reference a sample element in the retrieved header
引用已读取头部包含的一个示例元素
SampleTokenRef sampleRef = new SampleTokenRef(wsseHeader,"sample1");
SampleToken sample = sampleRef.GetSampleToken();

// Create a new WSSE header and add the element
生成新的安全头部信息并添加元素
WsseHeaderToken wsseNew = new WsseHeaderToken();
wsseNew.InsertToken(sample);

// Add sample element's processing in the new WSSE header
在生成的头部中处理示例元素
SampleProcessor sampleProcessor = new SampleProcessor();
sampleProcessor.SetReplaceTokens(true);
sampleProcessor.AddToken(sample);
wsseNew.AddProcessor(sampleProcessor);

wsseNew.ProcessHeader();

Element soap = wsseNew.GetSoapEnvelope();


框架
框架的结构层次很大程度上可以对应到WSSE规范描述的XML定义块上。工具包包含如下类型的对象:

·表示WSSE 头部的XML元素,也可以由子元素合成组合元素(compiste)。如果拥有用于生成标记的充足信息,那么可以从头开始构建WSSE标记, 又或已经从其他WSSE头部提取出(如SAML断言等)必要的XML元素, 那么可以通过封装来创建。 WSSE标记在工具包内的基类分别为位于wsse.Toolkit.Tokens包内的WsToken类以及WsCompisteToken类

·标记对象的“指针”,通过它们可以对现有的安全标记进行寻址和读取操作。更一般的作用是作为一种机制,方便客户指向现有的XML元素并将XML元素转化为标记对象。标记引用类层次的基类是位于wsse.Toolkit.Refs包内的WsTokenRef类

·标记处理器对象:表示工具包内的操作的对象,可以通过它们对WSSE头部、头部内任何子元素以及包含的SOAP信息进行操作。现在的工具包内仅有2个处理器类,DsigProcessor类以及EncProcessor类, 通过它们可以在WSSE头部中添加新的标记和(或者)改变已有标记。实际上,改动/添加标记的特性并不是处理器的必然需求,非改写的处理器类型也是可能出现的。这样的意图在wsse.Toolkit.Processors包内的处理器类型接口ITokenProcessor中得到体现,它的函数签名设计可以避免引入更多的标记类型。

·帮助类对象:wsse.Toolkit.Utils包内的许多帮助类,可以便于客户进行配置信息处理,XML处理等任务,还有wsse.Toolkit.Saml包用于支持SAML操作;wsse.Toolkit.Directory包用于支持用户目录操作。所有这些工具类本身不表示WSSE头部的任何部分,仅供工具包的其它组件使用。

·辅助包装器对象:此类对象将标记对象和处理器对象封装起来,组成WSSE安全头部的构建器,同时强调标记所有权概念,增强标记处理功能。 现在工具包内。扩展的标记类WsseHeaderToken, 不仅实现了标记对象接口,同时定义了一些便利方法,可以实例化工具包中的类并添加这些对象到本身表示的标记对象中。当然,如果需要,客户可以自由的直接操作工具包中的对象。

需要提到的是,并不是所有对象都是立即可得的。它们会随着工具包实现阶段的不断展开,在后续的文章中被依次介绍并添加到工具包中来(参见第一部分的结论部分)

如下,图1显示了工具包框架中各种对象以及客户间的关系。

图1. 工具包的操作

为了更好的理解图1,需要对工具包操作的几个重点概念进行进一步的解释:

·不是所有的标记元素都可以从现有XML元素生成。例如,重用现有时间戳元素(wsse.Toolkit.Tokens.Wss.TsToken标记)来构建新的标记,没有什么实际意义——实际上,需要时应该从头构建并相应添加新标记

·可从现有XML元素创建的标记类,具有唯一参数类型为org.w3c.dom.Element的构造函数,此构造函数会对输入的XML数据进行浅层次的数据有效性验证。所有情况下,必须正确地维护用于构建新标记XML元素的org.w3c.dom.Document对象,不合适的文档对象会在添加元素时产生错误。标记类基类WsToken类、WsConpositeToken类以及帮助类WsTokenHelper具有处理XML文档的功能。

·虽然标记引用类型也都是从基类wsse.Toolkit.Tokens.WsToken派生的,但是大多数引用类型的作用是引用现存的XML元素,不是作为本身可以被添加的元素。不过,在下面的WSSE映射部分会提到一些特殊的标记引用类型,除具有引用元素功能外,本身也可以作为被添加的元素。

·标记引用类型可以引用不同的安全信息头部中的标记元素——此功能有助于在新的WSSE头部中添加现有标记元素的功能的实现。标记引用类型甚至可以引用在安全处理过程的初期添加的当前不存在的元素, 比如前面代码示例中加密签名元素构成的元素。

·标记帮助类的责任是实例化标记类型对象和标记处理器对象,并将二者联系起来处理,当然这需要适当的配置信息以及初始化工作。标记处理器类型的责任是操作标记帮助类的处理结果,比如在安全头部中添加一个新产生的数字签名元素。处理器接口的要约是仅对引用标记进行适当的处理,并不对此处理过程中产生的新标记进行任何操作。

·处理操作可以连接起来构成处理操作链。这样,可以对多个安全头部的入口签名,然后对签名加密, 如上面客户处代码示例。

工具包提供了轻量的对象层次,处理每次客户调用时,会实例化一些具有仅于自己上下文环境关联的对象, 因此不必担心并发问题。工具包中大多数类没有提供同步化锁,只有wsse.Toolkit.Utils.Xml.XmlFactory 类和 wsse.Toolkit.Utils.Config.ConfigHelper类除外,这两个类提供了一些可以被多个线程共享的功能。对于配置的目录服务和SAML服务实现提供者来说,由于工具包的所有运行客户都访问相同的提供者,它们的实现必须是线程安全的。

WSSE映射
现在,将要讨论工具包内的组件是如何与WSSE规范规定的主要构建块的映射关系。注意:WSSE 规范的第5部分对头部块是这样定义的,“头部块以SOAP行动者或角色的形式存在,提供在在SOAP信息中添加针对特定接收者的安全相关信息的机制”, 这意味着, WSSE安全头部是可以扩展的, 同时在所有可能使用此技术的应用中试图使用它是不合适的。 因此,工具包框架仅对规范中规定的标记类型及其关系进行映射,同时可以在以后添加新的标记类型及其处理器。


图2.Web服务安全标准文档组织图

如图2所示,Web服务安全标准系统实际上由几个相关的标准文档组成。首要的是WSSE 规范,其中定义了欲添加到安全头部的信息的基本规则以及如何在SOAP信息中添加安全头部的规则。此规范是基本部分,仅包含安全标记XML元素定义的“骨架”部分,至于安全标记XML元素的内容定义以及应用规则,则由所谓的“侧面标准”文档(参考下文相关部分)确定。

一个完整的已签名WSSE头部文件,其中包含许多不同类型的安全标记以及一个SAML断言声明,可以使用IE或者基于Mozilla的浏览器可以在此文件超链接处浏览(也包含在可下载源代码中)。图3是一个包含几个标记及一个签名元素的WSSE头部,并附有相关标记的注解。


图3. 带有注解的WSSE头部

安全标记
WSSE规范的第6部分描述了可以添加到安全头部的各种不同类型的安全标记。这些在WSSE头部中携带的安全标记通常用于传送特定的安全信息到请求的目的服务处。WSSE规范并未强制确定传输信息的类型,这些信息的语义留给了相互通信的应用来协商确定。WSSE规范明确了对于支持的标记类型的添加和处理的规则。

在工具包中WSSE安全标记由wsse.Toolkit.Tokens.Wss包内的类表示,多数支持的标记类型都是从现有XML元素构建的——XML元素可以从某信息中提取然后再另一个信息中使用,这也是工具包的需求之一。下面描述的所有的标记都是可选的, 在安全头部中包含这些标记不是WSSE规范的要求,而是出于应用逻辑的需要。

构建一个特定标记并生成XML元素或者从现有XML元素构建标记时,会遵循标准对标记进行验证。XML元素的生成以及验证将会被延迟,直到标记的XML元素内容被明确访问才进行。这样可以避免过多的XML解析工作,并且可以实现唯一验证点,而不是在构建和更新XML元素的多个地方都进行验证。XML的构建以及添加依赖于标记顺序,在特定情况下, 标记顺序对于生成的安全头部的正确处理时很重要的。

工具包包含两种标记类型,表示单一XML元素的简单类型和可能包含其它标记的复合标记类型(由WsCompositeToken类)。复合类型标记的处理规则不同于简单类型,复合类型必须将任何操作(比如设定所属元素)传递到它的子元素,还要额外的为包含的子标记定义查询/替换等访问方法。


SOAP-ENV:mustUnderstand="1">
...



上面示例中的WSSE安全头部,在工具包内的由WsseHeaderToken头部标记类表示。它的功能包括:处理所有包含的安全标记、保证安全头部符合WSSE规范、生成头部XML元素等。它满足WSSE规范第5部分的要求,支持SOAP1.1协议中定义的行动者(actor)属性。可以在生成的头部中设置SOAP的mustUnderstand属性,但是对于此属性的正确处理应该在构建新的头部之前完成,因此,不在工具包的处理范围之内。

另外,WsseHeaderToken类还包含一些方法以辅助头部处理操作,如添加时间戳、对标记进行签名和加密等。如例 2所示,此类还具有供扩展使用的在类实例中添加新的标记处理器的通用方法。所有添加的标记处理器按照添加顺序被依次调用——这有助于保证在处理过程中新产生的XML元素可以被处理器链中稍后添加的标记处理器处理。



Admin

xcYjkd9Hjkksds...

WKjd73j0...



在WSSE规范6.2部分以及用户名称标记 概要标准第3部分中描述的户名名称标记类型由wsse.Toolkit.Tokens.Wss.UsernameToken类处理。 使用用户名称标记元素是传递用户名称(有时可以作为一种确认机制)以及他(她)的密码到目的服务处的标准方法。 此类型同时支持wsu:Id属性, 使得可以在其它处理节点(比如XML签名)处引用该标记元素。 包wsse.Toolkit.Directory内的辅助类具有从用户信息存储服务器处获取用户信息的功能——此功能通过wsse.Toolkit.Directory.IUserDirectory接口的方法表示。


EncodingType="wsse:Base64Binary"
wsu:Id="MyX509">
MIIOlskew78Hjkds...



在WSSE规范6.3部分以及X.509 标记 概要标准第3部分中描述的二进制标记类型, 可以传输密钥或者数字证书的信息。工具包中wsse.Toolkit.Tokens.Wss.BSTToken类支持此二进制标记类型。 由于XML具有基于文本的格式,在安全头部中添加二进制标记元素的内容前必须进行Base64编码转换。 虽然现在已经有若干(或正在标准化过程中)的标准,规定了不同(比如Kerberos信令)的二进制标记类型,工具包将仅支持使用更为广泛的X.509标记。

各种可能的XML安全标记具有很强的弹性, 彼此之间又有很大的差异, 因此, 对于如何在WSSE头部(WSSE标准6.4部分)附加此类标记请参考相应的标准文档——最低程度上, WSSE标准文档对于其它支持的标记类型提供了通用的添加框架。 工具包提供了wsse.Toolkit.Tokens.Wss.SamlAssertionToken类用于支持SAML标记标准, 此标准详尽描述了如何在WSSE安全头部内添加SAML断言。 相应断言的生成工作由配置的提供者完成,可以通过wsse.Toolkit.Saml.IAssertionGenerator接口获得此功能。

标记引用类型
一般来说, 提供良好的WSSE安全标记的引用框架并不是简单的任务, 特别的, 考虑每个元素可能在某特定的安全头部中被引用不止一次。 幸运的是, 工具包不需要提供一个通用的实现, 当从现有安全头部解析标记时, 可以合理的假设应用对于欲传输的安全标记有一定的控制规则。

标记引用类型的实现依赖于不同类型的标记如何获取或构建相应的类型实例的特征。 WSSE标准或者应用策略可能限制一些标记元素仅能在安全头部的某一个标记中使用, 比如时间戳元素, 或者拒绝对于包含多于一个用户名称XML元素的请求。 其它的可能限制包括:需要额外的查询上下文(比如签名者的公钥名称)以能够足够精确的从WSSE头部获得目的标记。





WSSE规范定义了wsse:SecurityTokenReference元素用于引用安全标记(可能是X.509证书或SAML断言)。 工具包中对于安全标记的引用通过wsse.Toolkit.Tokens.Refs.WsTokenRef的派生类实现。 一般在其它安全标记的处理过程中添加引用的元素, 因此不必明确的在WsCompositeToken对象中添加引用。 此规则的唯一例外是工具包中表示wsse:SecurityTokenReference XML元素的wsse.Toolkit.Tokens.Refs.Xml.SecureTokenRef类。

由于wsse:SecurityTokenReference元素被定义为可以引用几乎所有的可以想象出来的安全标记类型, 它的机构必然是很复杂的。 WSSE规范的7.1部分列出了应用于此标记的几个可能的引用机制。

·直接引用:如上例所示,这可能是最直观的、最明确的引用元素的方式。 此引用机制通过使用唯一的wsu:Id属性实现。 注意,这里也可以引用外部的URL.

·键标志符: 允许通过标记的唯一特征引用此标记, 因此, 每个标记的应用方式是依赖于标记定义标准的。 对于 X.509标记, 其键标志符是X.509证书的SubjectKeyIdentifier值(见X.509标记标准3.2.1部分)。

对于字符串型标记,包括在主WSSE规范中规定的键名称引用以及嵌入标记引用等还有一些引用机制。 限于篇幅有限,此处不再讨论。

标记处理
在简单传输安全标记之外, WSSE规范同时使用W3c的XML签名和XML加密推荐标准来保护SOAP消息的完整性和机密性, 工具包内, 这些功能的实现通过标记处理器来完成。 标记处理器的主要的用途是处理安全头部中已经存在的节点, 可能改变或者删除这些节点, 然后在头部添加新的节点以反映处理结果。 此行为通过wsse.Toolkit.Processors.ITokenProcessor接口定义, 具体的接口实现提供特定的逻辑。 现在, 工具包计划实现两个对于XML签名和加密的处理器,并在后续文章中讨论。

结论
本文在较高层次上考察了工具包的主要构件, 包括标记、引用、处理器等, 并就它们如何与Web服务安全标准的不同部分相对应进行了讨论。 在下篇文章中, 我们会剖析验证WSSE头部的需求并讨论Username标记、二进制标记以及SAML标记等的实现, 你会发现这些更有趣些。 这些已经在第一部分的开发计划部分提到了。

资源
本文讨论的工具包的项目源码以及项目文件使用Borland的Jbuilder集成开发环境开发,同时还提供了一个简陋的Windows批处理文件用于购建项目的源码,可以在此处下载。随着项目的进展,会更新以及添加实现文件,并在后续文章中提供。如果对于代码有任何建议,请给作者发邮件。作者喜欢将对于编程的讨论同正式讨论区分开来。

·Matrix-中文Java开发者社区:http://www.matrix.org.cn
·Part 1:http://www.matrix.org.cn/resource/article/43/43880_WS-Security.html
·OASIS WSSE规范PDF文档
·X509标记规范PDF文档
·SAML标记规范PDF文档
·源代码

Denis Piliptchouk 是BEA公司AquaLogic 企业安全工作组的高级技术成员,OASIS组织 Web服务安全标准(WSS)工作组成员,Web服务互操作组织(WS-I)基本安全标准(Basic Security Profile, BSP)委员会成员。他经常在业界出版物上发表文章。
Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd
↑返回目录
前一篇: 我们是否应该做更多的自动测试呢?
后一篇: 在你的代码中自动实现设计规范