现在距Web服务安全(WS-Security)规范推出已经超过一年了。然而,该技术的实现试图循着Web服务开发的足迹,目前进展缓慢。本文将介绍当前Java社区中的WS-Security实现,以及趋势和正在进行的标准化工作。它对WS-Secutity的各个方面进行了快速介绍,包括关键WS-Security概念的使用和重要性,如令牌、XML加密、规范化、XML签名和政策。它也简略介绍了相关的安全标准,如SAML、XACML、XrMS、Kerberos和XKMS,以及Web服务安全的其他重要方面(如单一登录、联邦和安全会话等)。然后本文件提供了Web服务工具供应商(如Apache AXIS、BEA WebLogic、IBM WebSphere和Microsoft .NET)的WS-Security的实现实例。还将详细比较这些使用支持WS-Security的Web服务平台之间互操作性的实际演示。
|
最后,您将会看到一个使用当前Java技术的Web服务的实际应用程序。另外,您也将会了解WS-Security的发展前景、在Java中实施强大的WS-Security方案将会遇到的问题。
|
下载 作者提供的与本文相关的文件
|
WS-Security:
对Web服务的最显著障碍是端到端的安全性,WS-Security描述了对SOAP消息的改进,通过消息完整性、消息保密性和单一消息认证提供了保护能力。WS-Security也为安全令牌和消息的关联提供了一个通用机制。WS-Security不需要明确类型的安全令牌。另外,WS-Security描述如何编码二进制安全令牌。特别是,规范描述了如何编码X.509证书和Kerberos票据,以及如何包含难懂的加密键。
简而言之,WS-Security的目标是使应用程序能够构建安全的SOAP消息交换、获得端到端的消息级安全(不止是传输级的安全)。
令牌:
安全令牌 —— 一个安全令牌代表一个声称集合,一个声称是一个实体所作的声明(举例来说,名称、身份、键、组、特权、功能等)。
签署的安全令牌 —— 签署的安全令牌是一个被特定授权机构宣称和加密签署的安全令牌(举例来说,一个X.509证书和Kerberos票据)。
有两种令牌:
· 未签署的安全令牌(例如:用户名)
· 签署的安全令牌(例如:X.509证书,Kerberos票据)
图1.1
根据Oasis规范,下面给出了一个使用用户名的SOAP消息的例子:
|
<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope"
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
<S:Header>
...
<wsse:Security>
<wsse:UsernameToken>
<wsse:Username>WebLogic</wsse:Username>
<wsse:Password>WebLogic</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
...
</S:Header>
...
</S:Envelope>
|
BEA WebLogic Workshop示例:用户名令牌
下面给出了一个Workshop Web服务使用的WSSE策略文件示例。该策略定义每一个进入的SOAP消息必须附有一个用户名和密码,流出的SOAP消息在被发送到线上前应该附有一个用户名和密码。
|
<?xml version="1.0" ?>
<wsSecurityPolicy xsi:schemaLocation="WSSecurity-policy.xsd"
xmlns="http://www.bea.com/2003/03/wsse/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
流入的SOAP消息必须附有一个用户名和密码。
-->
<wsSecurityIn>
<token tokenType="username"/>
</wsSecurityIn>
<!--
在将流出的SOAP消息发送到线上前,附加用户名和密码。
-->
<wsSecurityOut>
<userNameToken>
<userName>weblogic</userName>
<password type="TEXT">weblogic</password>
</userNameToken>
</wsSecurityOut>
</wsSecurityPolicy>
|
下面的例子说明了BinarySecurityToken的使用:
|
<wsse:BinarySecurityToken
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"
Id="myBinaryToken"
ValueType="wsse:X509v3"
EncodingType="wsse:Base64Binary">
MIIEZzCCA9CgZsDer9IQEmtJZc0...
</wsse:BinarySecurityToken>
|
XML签名:
XML签名用于认证发送者的身份、确保SOAP消息的完整性。如果进入的SOAP消息任何部分在传输中被修改,那么接收者执行的签名验证将会失败。
WS-Security规范考虑了一个消息附加多个签名,每个签名指向消息的不同、甚至是重叠的部分。这对于许多消息在多个处理阶段流动的分布式应用程序非常重要。
BEA WebLogic Workshop示例:用于流入和流出SOAP消息的XML签名
WSSE策略文件内容:
|
<wsSecurityPolicy xsi:schemaLocation="WSSecurity-policy.xsd"xmlns="http://www.bea.com/2003/03/wsse/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsSecurityIn>
<!--
流入的SOAP消息必须用发送者的私有键进行数字签署。
发送者的公开键用于验证签名。
-->
<signatureRequired>true</signatureRequired>
</wsSecurityIn>
<wsSecurityOut>
<!--
用发送者的私有键签署SOAP消息。只有发送者的公开键能够验证签名。确保发送者的认证,也就是,发送者实际上是SOAP消息的来源。
-->
<signatureKey>
<alias>mycompany</alias>
<password>password</password>
</signatureKey>
</wsSecurityOut>
<!--
在缺省位置、服务器域根、以及这里情况下的BEA_HOMEWebLogic81samplesdomainsworkshop查找发送者的.jks keystore。
-->
<keyStore>
<keyStoreLocation>samples_sender.jks</keyStoreLocation>
<keyStorePassword>password</keyStorePassword>
</keyStore>
</wsSecurityPolicy>
|
XML加密:
该规格允许任何body块、header块、这些子结构、附件的组合被发送者和接收者共享的通用对称键或消息中以加密形式携带的键所加密。
为什么加密?
考虑下面假定的支付信息,其包括身份信息和支付方法的信息(如信用卡、货币转账或电子支票):
|
<?xml version='1.0'?>
<PaymentInfo xmlns='http://example.org/paymentv2'>
<Name>John Smith </Name>
<CreditCard Limit='5,000' Currency='USD'>
<Number>4019 2445 0277 5567 </Number>
<Issuer>Example Bank </Issuer>
<Expiration>04/02 </Expiration>
</CreditCard>
</PaymentInfo>
|
上面的标记指出John Smith使用他的信用卡,限额是美元。
加密一个XML元素:
Smith的信用卡号是敏感信息。如果应用程序希望该信息保密,那么它可以加密CreditCard元素:
|
<?xml version='1.0'?>
<PaymentInfo xmlns='http://example.org/paymentv2'>
<Name>John Smith</Name>
<EncryptedData Type='http://www.w3.org/2001/04/xmlenc#Element'
xmlns='http://www.w3.org/2001/04/xmlenc#'>
<CipherData>
<CipherValue>A23B45C56</CipherValue>
</CipherData>
</EncryptedData>
</PaymentInfo>
|
通过从开始标签到结束标签加密整个CreditCard元素,隐藏了元素本身的标识。(监听者不知道他是在使用信用卡还是货币转账。)CipherData元素包含了CreditCard元素加密后的序号。
BEA WebLogic Workshop示例:用于流入和流出的SOAP消息的XML加密
WSSE策略文件内容:
|
<wsSecurityPolicy xsi:schemaLocation="WSSecurity-policy.xsd"
xmlns="http://www.bea.com/2003/03/wsse/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wsSecurityOut>
<!--
用接收者的公开键加密SOAP消息。只有接收者的私有键能够解密它。
确保SOAP消息的保密性。(该过程需要发送者的keystore已经包含一个数字证书,该证书包含接收者的公开键。)
-->
<encryption>
<encryptionKey>
<alias>mycompany</alias>
</encryptionKey>
</encryption>
</wsSecurityOut>
<wsSecurityIn>
<!—流入的SOAP消息必须用客户的公开键加密。用来访问keystore中客户的解密私有键的别名和密码由下面的<decryptionKey>元素提供。. -->
<encryptionRequired>
<decryptionKey>
<alias>client1</alias>
<password>password</password>
</decryptionKey>
</encryptionRequired>
</wsSecurityIn>
<!--
在缺省位置、服务器域根、以及这种情况下的BEA_HOMEWebLogic81samplesdomainsworkshop 查找客户的.jks keystore。
-->
<keyStore>
<keyStoreLocation>samples_client.jks</keyStoreLocation>
<keyStorePassword>password</keyStorePassword>
<</keyStore>
</wsSecurityPolicy>
|
算法:
下面的表格概要描述了WS-Security推荐的额外算法:
|
算法类型
|
算法
|
算法URI
|
|
规范化
|
专有的XML规范化
|
http://www.w3.org/2001/10/xml-exc-c14n
|
|
转换
|
XML解密转换
|
http://www.w3.org/2001/04/decrypt
|
专有的XML规范化算法处理通用规范化的缺陷,该缺陷由于具有预先存在签名的有漏洞的名称空间而发生。
最后,如果发送者希望在加密前签署一个消息,那么发送者应该为XML签名使用解密转换。
安全需求与技术:
认证: 用户名/密码,基于键的数字签名和确认,智能卡等
授权: 策略应用,访问控制
审核多样化: 登录表格,本身受到保护避免篡改
认可: 基于键的数字签署和签名确认
完整性: 基于键的数字签署和签名确认,消息可靠性
保密性: 基于键的加密和解密
信任: 基于键的数字签署和签名确认,消息可靠性
基于XML的安全基础架构:
SAML:
SAML是一个用于在Internet上通过XML文档共享安全信息的开放框架:
· SAML声称作关于主题(个体或服务)的声明
· 三种SAML声称:认证、属性、授权
· SAML声称能够被数字签署
· 声称由“授权机构”发布
认证SAML声称的例子:
通过将声称元素放置在header中,SAML声称附着于使用WS-Security的SOAP消息。下面的例子说明了一个具有SAML声称令牌的SOAP消息:
|
<saml:Assertation MajorVersion="1" MinorVersion="0"
AssertionID="186CB370-5C81-4716-8F65-F0B4FC4B4A0B"
Issuer="www.test.com" IssueInstant="2001-05-31T13:20:00-05:00">
<saml:Conditions NotBefore="2001-05-31T13:20:00-05:00" NotAfter="2001-05-31T13:25:00-05:00"/>
<saml:AuthenticationStatement AuthenticationMethod="password"
AuthenticationInstant="2001-05-31T13:21:00-05:00">
<saml:Subject>
<saml:NameIdentifier>
<SecurityDomain>"www.example.com"</SecurityDomain>
<Name>"cn=Alice,co=example,ou=sales"</Name>
</saml:NameIdentifier>
</saml:Subject>
</saml:AuthenticationStatement>
</saml:Assertion>
|
SAML响应示例:
|
<samlp:Response MajorVersion="1" MinorVersion="0" RequestID="186CD370-181-4236-8F65-
F0B4FC4B4A0B" InResponseTo="EE52CAF4-3452-4ebe-84D3-4D372C892A5D"
StatusCode="Success">
<saml:Assertion MajorVersion="1" MinorVersion="0" AssertionID="186CD370-5C81-4716-8F65-
F0B4FC4B4A0B" Issuer="www.test.com">
<saml:Conditions NotBefore="2001-05-31T13:20:00-05:00"
NotAfter="2001-05-31T13:25:00-05:00"/>
<saml:AuthorizationDecisionStatement/>
</saml:Assertion>
</samlp:Request>
|
XACML:
Extensible Access Control Markup Language (XACML)是一个描述策略语言和访问控制决策请求/响应语言(都是在XML中编写)的OASIS标准。策略语言用于描述通用访问控制需求,具有定义新功能和数据类型、合并逻辑等的标准扩展点。请求/响应语言让您能够建立一个查询询问给定的动作能否被允许,并解释结果。响应将会是四个值之一:允许,拒绝,不确定(错误发生或一些需要的值丢失,因此无法进行决策)或不可用(请求无法被该服务应答)。
XACML规定了基于几个标准的活动的细粒度控制,包括:
· 用户请求访问的属性(如,“只有公司经理和以上职位可以阅览该文档”)
· 做出请求所基于的协议(如,“该数据只能在通过HTTPS访问时被访问”)
· 认证机制(如,“请求者必须使用数字设备来验证”)
XACML策略包括头信息、一个可选的对策略的文本描述、一个目标、一个或多个规则和一个可选的职责集。
一个XACML请求的示例:
|
<?xml version="1.0" encoding="UTF-8"?>
<Request
xmlns="urn:oasis:names:tc:xacml:1.0:context"xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:oasis:names:tc:xacml:1.0:context
http://www.oasis-open.org/tc/xacml/1.0/sc-xacml-schema-context-01.xsd">
<Subject>
<Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
DataType="identifier:rfc822name">
<AttributeValue>bs.com</AttributeValue>
</Attribute>
</Subject>
<Resource>
<Attribute AttributeId="identifier:resource:resource-uri" DataType="xs:anyURI">
<AttributeValue>http://medico.com/record/patient/BartSimpson</AttributeValue>
</Attribute>
</Resource>
<Action>
<Attribute AttributeId="identifier:action:action-id" DataType="xs:string">
<AttributeValue>read</AttributeValue>
</Attribute>
</Action>
</Request>
|
一个XACML响应的示例:
|
<?xml version="1.0" encoding="UTF-8"?>
<Response
xmlns="urn:oasis:names:tc:xacml:1.0:context"
xsi:schemaLocation="urn:oasis:names:tc:xacml:1.0:context
http://www.oasis-open.org/tc/xacml/1.0/sc-xacml-schema-context-01.xsd">
<Result>
<Decision>Deny</Decision>
</Result>
</Response>
|
XrML:
Extensible Rule Markup Language (XRML)是一个通用目的的、基于XML的规范语法,用于表达与数字内容、服务或任何数字资源相关联的权利和条件。
下面的例子描述了一个使用指向XRML令牌的XML签名的消息。
|
<S:Envelope xmlns:S="...">
<S:Header>
<wsse:Security xmlns:wsse="...">
<xrml:license xmlns:xrml="..."
licenseId="urn:SecurityToken-ef375268"/>
...
</xrml:license>
<ds:Signature xmlns:ds="...">
...
<ds:KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference URI="urn:SecurityToken-ef375268"
xmltok:RefType="xrml:license"
xmlns:xmltok="..."/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
...
</wsse:Security>
</S:Header>
<S:Body>
...
</S:Body>
</S:Envelope>
|
Kerberos:
Kerberos是一个已经建立的认证和安全基础架构。与Web服务安全的集成需要下面的动作:
· 请求和发行安全令牌
· 将安全令牌附着于消息
· 建立一个安全上下文
· 使用安全上下文签署和加密消息
下面的示例消息说明了使用Kerberos令牌进行的签署:
|
<?xml version="1.0" encoding="utf-8"?>
<S:Envelope xmlns:S="http://www.w3.org/2001/12/soap-envelope">
<S:Header> ...
<wsse:Security
xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/07/secext">
<wsse:BinarySecurityToken id="Kerberosv5ST" wsse:ValueType="wsse:Kerberosv5ST"
wsse:EncodingType="wsse:Base64Binary">
MIIEZzCCA9CgAwIBAgIQEmtJZc0rqrKh5i...
</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-excc14n#"/>
<ds:SignatureMethod
Algorithm="...#DES-MD5"/> ………….
|
联邦:
联邦是一个已经建立信任的领域/范围的集合。信任的水平可能不同,但它典型情况下包括认证,还可能包括授权。
联邦提供一种简单、灵活的机制,用于识别和验证来自合作伙伴组织的用户,并在可信的联邦内为他们提供对Web站点的无缝访问,而不需要重新认证。另外,联邦标准也处理提供关于用户(如角色和组信息)的可信属性的事务(如,X509证书,X509v3属性证书,Kerberos令牌,SAML声称),考虑了隐私和特定业务规则。
联邦也确保同一用户跨公司的不同身份能够使用联合管理技术在两个合作伙伴之间安全地链接。联邦参加者能够交换身份信息,因此信任的各方能够独立地在其领域内验证用户的身份。
在发出域和信任域(联合的服务提供者)之间的联合单一登录促进了用户标识和其他属性相关信息(如,授权角色和组成员资格、用户权利,如。EmployeeID、SSN、PIN #)的安全和可信任的转移。联合身份管理定义了一个过程,通过该过程信任的参与者能够基于从发出方接收到的信息确定用户的本地有效标识符。转移的细节可能涉及业务和用户原有企业之间的多个消息,这对于用户是透明的。
联邦规范提供了一个通用模型和框架;profile描述了模型如何应用到这些不同的环境中。额外的profile可能会被指定,用于将模型集成到其他环境中。
每个profile规范定义了该机制在WS-Federation中如何应用,如果完全是对于一个给定的环境,例如被动或主动的请求者。
单一登录:
单一登录(SSO)是一个为用户提供一次登录、获得对所有应用程序和资源认证访问的方法。
单一登录标准(现在的编码名称为XSSO)的目的是定义支持以下内容的服务:
· 应用程序的开发是为了为企业提供一个通用的、单次最终用户登录界面
· The development of applications for the coordinated management of multiple user account management information bases maintained by an enterprise.
单一登录可以使用用户名/密码、令牌(例如Kerberos)或声称(SAML等)来获得。在后面有一个使用SAML声称的单一登录的例子。
一个遵守SAML的服务,称为一个可信方,向一个颁发授权机构发送SAML请求,该机构返回SAML声称响应。例如,当一个用户登录进遵守SAML的服务中时,服务发送一个“认证声称请求”给颁发授权机构,指出该用户在特定时间以特定方法得到了认证。颁发授权机构返回一个“认证声称参考”,服务能够将其传递给其他站点,因此它们能够检查用户的证书。稍后,当用户访问另一个遵守SAML的需要认证的站点时,该站点使用该参考来从颁发授权机构请求认证声称,该机构将返回一个“认证声称”,指出该用户实际上已经在特定时间被特定方法认证过。
在当前的规范中,有四种类型的声称:
· 认证声称
· 属性声称
· 授权声称
· 主体声称
当一个用户通过登录服务创建SAML请求时,声称由颁发授权机构产生,并通过HTTP在一个SOAP封装内传输,独立于授权机构的类型。
Web服务安全规范
本文中描述的模型和方法利用了白皮书“Security in a Web Services World: A Proposed Architecture and Roadmap”中描述的规范。下面对关键的规范进行了总结:
· WS-Security描述了如何将签名和加密的header附加到SOAP消息。另外,它还描述了如何将安全令牌(包括二进制安全令牌,如X.509证书和Kerberos票据)附加到消息。
· WS-Policy代表了一套规范,它们描述了中间点和端点(例如,需要安全令牌,支持加密算法、隐私规则)上的安全(和其他业务)策略的功能和约束,以及如何将策略与服务和端点关联起来。
· WS-Trust描述了一个用于信任模型的框架,它使Web服务能够通过请求、发布和交换安全令牌安全地互操作。
· WS-Privacy将描述一个模型,该模型用于描述Web服务和请求者如何宣称隐私偏好和组织隐私实践声明。
· WS-SecureConversation描述了如何管理和认证团体间的消息交换,包括安全上下文交换和建立与得到会话键。
· WS-Federation描述了如何在一个异构的联合环境中管理和代理信任关系,包括对联合身份、属性共享和假名管理的支持。
· WS-Authorization将描述如何管理授权数据和授权策略。
另外,其他几个关键Web服务规范完成规范的基础层:
· WS-Addressing描述如何为消息指定身份证明和寻址信息。
· WS-MetadataExchange描述了如何交换元数据,例如在服务和端点之间的WS-Policy信息和WSDL。
· WS-ReliableMessaging描述了如何在网络不可靠的情况下确保消息传递可靠。
· WS-Transactions和WS-Coordination描述如何使处理的操作能够成为Web服务消息交换的部分。
以上规范与互操作性profile的结合使客户能够轻易地创建可互操作的、安全可靠处理的Web服务,它通过组成联邦和安全规范在联邦内或跨联邦与其他Web服务规范集成。
一些Web服务工具供应商的WS-Security实施的代码示例:
实施UserToken的示例
1. BEA Workshop示例(从BEA Workshop示例中摘取)
userToken示例
userToken示例展示了一个同步Web服务通信的简单情况,其中两个Web服务都需要用户名和密码。
Web服务A发送一个SOAP消息给Web服务B的hello()方法。Web服务B通过发送一个包含hello()方法返回值的SOAP消息进行响应。两个Web服务都需要流入的SOAP消息附有一个用户名和密码,在流出的消息被发送到线上前,两个Web服务都使用一个用户名和密码包装它们。
下图展示了调用的SOAP消息和返回的SOAP消息如何被WSSE处理。
该示例的源代码存在于zip文件BEA-Workshop-sample.zip中。
为了使流入的SOAP消息附有用户名和密码,WSSE策略文件应该具有以下代码片段:
|
<! – 流入的SOAP消息必须附有用户名和密码。 -->
<wsSecurityIn>
<token tokenType="username"/>
</wsSecurityIn>
|
为了在将流出的SOAP消息发送回去前使其附有一个用户名和密码,WSSE策略文件应该具有以下代码片段:
|
<!--
在将流出的SOAP消息发送到线上前,将其附上一个用户名和密码。
-->
<wsSecurityOut>
<userNameToken>
<userName>WebLogic </userName>
<password type="TEXT">WebLogic </password>
</userNameToken>
</wsSecurityOut>
|
2. Axis示例(从http://axis-wsse.sourceforge.net/中摘取)
下面的Axis示例实现了‹UsernameToken›规范(Web服务安全UsernameToken profile)
· 没有密码
· 清除密码
· 密码摘要
· 密码+目前+时间戳摘要
该示例在zip文件Axis-Sample.zip中提供,其中还包括文件readme.txt。
Web服务调用的请求和响应显示在下面:请求:
|
POST /mscomservice/mscom.asmx HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.1
Host: ws.microsoft.com
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: "http://www.microsoft.com/GetVersion"
Content-Length: 911
Authorization: Basic QjhmZQvNE***hidden***QjhmZQvNE
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="0"
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext">
<wsse:UsernameToken>
<wsse:Username xsi:type="xsd:string">
B8ffemWZ1***hidden***wYJJW4bua0+</wsse:Username>
<wsse:Password Type="wsse:PasswordDigest"
xsi:type="xsd:string">
BF3utb***hidden***0lKZz4quA=</wsse:Password>
<wsse:Nonce xsi:type="xsd:string">
msJPTHku44rHAqPIRvbNQA==</wsse:Nonce>
<wsu:Created xsi:type="xsd:string"
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
2003-10-13T19:50:57Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<GetVersion xmlns=""/>
</soapenv:Body>
</soapenv:Envelope>
|
响应:
|
HTTP/1.1 200 OK
Connection: close
Date: Mon, 13 Oct 2003 18:50:52 GMT
Server: Microsoft-IIS/6.0
P3P: CP='ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI
TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI'
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 607
| |