web数据安全架构_Web服务架构–第一部分:基本数据类型

web数据安全架构

XML消息交换是大多数Web服务(包括SOAP和REST方法)的基础。 XML的使用带来了一些缺点,包括性能方面的潜在问题,但它也提供了某种抽象级别,允许在涉及交换的各方之间进行松散耦合。 但是,为了使这种松散耦合真正起作用,您需要能够以允许验证正确文档的方式定义正在交换的XML文档的结构。 W3C的XML Schema定义语言(在本文的其余部分中将被称为“模式”)是最广泛用于这些消息结构定义的方法。

大多数Web服务应用程序不直接使用XML文档,而是经过Web服务工具包中的数据绑定转换层。 这对应用程序开发人员很方便,因为这意味着他们可以使用所选的编程语言直接处理数据结构。 但是数据绑定步骤需要处理架构数据类型和结构与编程语言数据类型和结构之间的不匹配,并且这些不匹配会给应用程序造成问题。 如果您希望Web服务提供一致的跨平台兼容性(通常首先要使用Web服务的重点),则需要设计架构定义以避免潜在的问题区域-或至少要意识到使用有问题的架构功能所涉及的风险。

在本系列文章中,我们将研究模式和Web服务数据绑定之间不匹配引起的各种类型的问题。 对于第一篇文章,我们将从最基本的层次开始,着眼于简单的数据类型及其所产生的问题。

代表数字

涉及业务数据时,数字值与您获得的基本值差不多。 考虑到数字的重要性,您可能会认为这是架构可以平稳且一致地工作的领域。 从抽象的意义上讲,它的确是这样-但是当架构被Web服务工具箱应用时,您仍然会遇到很多问题。

问题的一部分是内置模式数字数据类型的种类繁多。 图1显示了此区域中涉及的模式数据类型树的部分。 要理解它,请从专业化角度考虑-向下移动倒置树的一个分支越深,由类型表示的数据就越专业化。 在顶层的常规anySimpleType下,是三个基本数字类型float,decimal和double。 float和double是终端类型,与浮点数的IEEE标准匹配,因此在Web服务平台之间提供了出色的互操作性:每种主流编程语言都支持与float规范匹配的32位浮点数和与64位浮点数匹配的32位浮点数。双重模式规范,因此Web服务工具包可以将它们直接映射到本地语言类型。 特殊值(非数字,正负负无穷大以及正负零负)的编程语言文本表示形式与模式所使用的表示形式之间可能存在细微差异,但是工具箱可以轻松地处理翻译。

图1.模式数字类型

这是当您沿着树的小数点分支下来时开始遇到问题的。 十进制本身定义为任意数量的十进制数字的字符串,带有可选的前导符号和可选的小数点。 整数十进制的直接后代)与对应于十进制的值的子集匹配,因为它允许任意数量的十进制数字,带有可选的前导符号,但不允许小数点。 在nonPositiveIntegernonNegativeInteger的情况下, 整数的后代通过分别禁止大于或小于零的值来限制允许的值,而在long的情况下,通过将值的范围限制为64位2s补码等效值来进一步限制允许的值。 int,shortbyte进一步将范围限制为分别为32位,16位和8位2s补码, 而无符号变量匹配相同位数的无符号值。

所有主要的编程语言都支持沿树的主分支匹配long,intshort模式类型的值,但其他变体会带来潜在的问题。 例如,Java不包含与unsignedLongunsignedInt相对应的原始类型。 Java Web服务框架通常通过使用特殊的类而不是这些类型的原语来解决缺少语言支持的问题,但这会使Web服务接口有些尴尬并且会产生性能问题(因为在Java语言中使用原语时,其速度通常比对象类型快得多)。计算)。

甚至十进制整数类型也存在问题。 大多数Java工具箱使用标准的j ava.lang.BigDecimal和java.lang.BigInteger类来处理这些类,这些类的性能较差,但支持大小不受限制的值。 .Net而是使用固定大小的128位表示形式,该表示形式限制了可能的值范围(如架构规范所允许),但提供了相对较好的性能。

模式数字类型是混乱且不一致的(例如,为什么为什么要使用nonPositiveInteger类型,而不要使用nonPositiveDecimal类型?),并且在任何情况下通常都只表示语法糖(因为可以使用simpleType限制来实现范围)。 由于这些原因,最好避免在模式定义中使用大多数这些类型,尤其是那些打算与Web服务一起使用的类型。 尽可能使用特定大小的类型(对实数使用doublefloat ,对整数使用longint ),因为这些类型一致地转换为编程语言原始类型。 如果您需要使用超出这些大小类型可能的范围或精度的值,请理解由于实现上的差异, 十进制整数不一定会为您提供所需的值,而是考虑使用字符串并在其中处理值的转换。应用程序代码。

时间问题

与时间相关的值是使用模式时出现问题的另一个常见原因。 架构定义了9种与时间相关的独立数据类型,所有数据类型均基于Western Gregorian日历的特定版本。 与数字类型不同,与时间相关的类型并非以任何形式的特殊化关系直接出现,而是被视为直接从泛型anySimpleType派生而来。

最广泛使用的时间数据类型是dateTime,datetime 。 这三种数据类型共享一种通用的表示形式,通常以dateTime表示。 这是我撰写本文时当前时间的示例dateTime值:“ 2008-09-08T15:38:53”。 日期值使用与dateTime相同的表示形式,但是去掉了'T'和随后的时分秒值(在这种情况下,保留“ 2008-09-08”); 相反, 时间值会剥夺所有包括“ T”在内的所有内容,仅保留时分秒值(“ 15:38:53”)。

到目前为止看起来很简单,对吧? 令人困惑的是这些值之一的实际解释。 日期和时间因您所在的位置而异,通常以时区表示。 例如,当我在新西兰写这篇文章时,我的时间比世界标准时间早12点,比美国西海岸目前有效的太平洋夏令时间早19小时。与此同时,我在此处写下示例dateTime值如“ 2008-09-08T15:38:53”,西雅图时间为“ 2008-09-07T20:38:53”。

对于许多应用程序,您需要以允许将一个值与另一个值关联的方式指定日期/时间。 架构通过允许日期/时间值使用附加的时区指示来支持此要求。 该时区指示可以采用字母“ Z”的形式,用于指示日期/时间的通用时间(UTC)值,也可以相对于通用时间以小时和分钟为单位进行偏移。 因此,这些dateTime值(以及更多其他变体)中的任何一个都可以用于指示同一时刻:“ 2008-09-08T15:38:53 + 12:00”,“ 2008-09-07T20:38:53-08 :00”或“ 2008-09-08T03:38:53Z”。

但是架构不需要您指定时区指示,并且没有这种指示,日期/时间值只能被解释为对于世界上任何地方的任意位置都是准确的。 对于某些可能只是您想要的应用程序-例如,一个人的出生日期通常被视为一个特定的日期,而无需参考位置,人们同样会在世界各地庆祝公历新年-但对于其他人应用程序会产生重大问题。 考虑电话会议的情况,例如,所有相关方都需要将事件的时间与他们的本地时钟进行协调。

不幸的是,模式不允许您区分需要完全指定日期/时间的情况和允许甚至期望无区域值的情况(至少不能以Web服务工具包可以解释的方式进行区分)这可以通过使用simpleType限制模式进行,但工具包通常会忽略这些模式)。 因此,此时的模式含糊不清,这意味着工具箱需要处理带或不带时区指示的值。

处理这两种类型的值的需求在解释方面造成了一些头疼的问题,特别是因为编程语言通常基于绝对时间值来实现日期/时间处理。 根本无法正确将缺少时区指示的架构值转换为绝对时间。 当然,无论如何,这并不会阻止工具箱执行此类值的操作。 在大多数情况下,他们通过假设以当地时区给出的值来转换所提供的值,而这通常是您想要的-但是,如果不是,则很难隔离所产生的问题。

对于日期类型,时区引起的问题尤其混乱。 人们通常将日期视为日历上的固定时间段。 例如,当您签署法律文件时,通常会填写签名日期。 如果您同意一个新项目,通常会有一个预定的完成日期(因为这些预定日期有时可能很奇怪)。 如果在购物时要求您出示驾驶执照以证明年龄,则店员会查看您的出生日期,并将其与年龄限制进行比较。 在所有这些情况下,日期都被视为具有日期分辨率,通常会忽略时区之间的差异。 但是架构日期类型使用关联的时区指示,就像dateTime和时间类型一样。 时区指示的这种使用在模式日期类型和日期的常见形式之间造成了断开。 通常,这可以通过将日期转换为00:00(午夜,作为一天的开始时间)来表示,该时间代表在指定的任何时区中该天的开始时间。 但是,如果您随后使用本地时区打印出该日期值,则可能会发现它与文档中最初指定的日期值不同。

如果架构为带有时区规范的日期/时间值定义了单独的类型,而没有时区规范的则为应用程序轻松选择他们想要使用的类型。 没有这种能力,工具箱就很难解决模式中日期/时间值的基本缺陷表示。 Java的JAXB 2.0采用了可能是最全面的方法来解决此问题,并使用一个特殊类( javax.xml.datatype.XmlGregorianCalendar )处理所有模式日期/时间类型,该类直接对应于模式表示形式。 这种方法保留了值的模式表示的所有细微差别,但以将解释问题传递给开发人员为代价。 其他工具箱通常只使用默认值,例如假设本地时区。

鉴于该领域存在棘手的问题,最好的通用方法可能是仅将模式日期/时间类型用于应使用时区指示完全指定的值,并确保生成的任何文档都包含时区适应症。 大多数Web服务工具箱都会在输出时自动为您生成时区指示,因此这最后一部分很容易。 要求输入文档还使用时区指示可能会更加困难,特别是因为文档可能正在经历多个处理阶段。 如果要确定不会因错误的转换假设而导致问题,则最好的解决方案可能是在模式表示中使用字符串类型,以便您的Web服务工具包无需尝试即可将值传递给应用程序代码解释价值。

如果您需要无区域的日期/时间值(例如出生日期示例),则最好的方法可能还是在模式表示中使用字符串类型。 从提供模式中数据的准确表示的角度来看,这不是很令人满意,但是避免了Web服务工具箱将未分区的值解释为本地时区的问题。

参考资料

应用程序内部使用的数据结构通常包含组件之间的多个链接,包括交叉引用和间接关联。 另一方面,XML本质上是树结构的。 通过包含表示XML中的一对多关系非常容易,但是任何其他类型的关系都是有问题的。 甚至一对多关系也可能是低效的。 例如,考虑一个文档列出客户的订单历史记录的情况。 每个订单将具有关联的帐单和送货地址,但是这些地址通常会从一个订单重复到下一个订单。 如果仅将地址嵌入每个订单的信息中,最终将在文档中包含大量冗余信息。

引用可用于解决XML树结构的限制。 引用的想法是您在XML文档中一次定义了一些内容,包括唯一标识符。 每当其他数据需要使用该定义时,就可以使用唯一标识符创建引用。

模式直接支持两种形式的引用。 第一个使用ID类型定义元素标识符,可以使用IDREF或IDREFS类型从文档中的任何位置链接元素标识符。 ID / IDREF链接的好处是它们很简单-标识符只是名称,任何类型的元素都可以在模式中定义ID值。 ID / IDREF链接的缺点是它们使用全局上下文,因此无法说必须在特定元素类型上定义用于特定IDREF的值,并且用作ID值的名称在文档(甚至跨元素类型)。 某些Web服务工具箱支持使用ID / IDREF链接来表示数据结构中的引用(包括JAX-WS / JAXB 2.0和与JiBX数据绑定一起使用的Apache Axis2); 其他工具包(例如.Net和ADB使用的Axis2)则没有,而是将IDREF值视为简单的文本字符串。

模式支持的第二种引用类型是键/键引用链接。 尽管ID / IDREF链接是使用数据类型定义的,但key / keyref链接却是模式定义结构的一部分。 这种差异使键/键引用链接比ID / IDREF链接更具表现力,包括定义键值唯一的上下文。 但是,由于键/键引用链接的设计目的更多是为了文档验证而不是结构化,因此它们很复杂,并且通常不被用于将XML数据与数据结构相互转换的数据绑定框架使用。

因此,如果您想将链接嵌入XML文档中并由Web服务工具包处理它们,则唯一的希望就是ID / IDREF方法。 一些工具包将直接支持这些链接。 其他人只会将标识符值视为字符串,但是您可以编写应用程序代码来交叉引用标识符和参考值并建立自己的链接。

结论

在本文中,我们研究了在Web服务中使用最常见的架构数据类型时出现的一些问题。 除了本文提到的类型外,还有许多其他专用的模式数据类型(总共42种!),其中一些还会带来其他问题。 作为一般原则,采用Web服务模式定义的最佳方法是避免使用过度专业化的类型(与常规编程语言类型匹配的数字类型除外),并在需要完全控制时使用字符串类型对价值的解释。

值得指出的是,尽管本文讨论的某些问题可以通过数据绑定框架更好地解决,但是很多问题都在于模式本身。 尤其是,数据/时间类型的族群在处理区域值和非区域值类型之间缺乏区别,因此充其量是最麻烦的,最糟糕的是会导致错误。 就像JAXB对XmlGregorianCalendar类型所做的那样,可能会将混乱传递给用户,但这并不是真正的解决方案。

翻译自: https://www.infoq.com/articles/schema-for-ws-part1/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

web数据安全架构

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值