time 
设为首页】【收藏本站
当前位置: 主页 > 软件工程 > 分析与建模 > XML 安全:使用 SAML 确保可移植的信任

XML 安全:使用 SAML 确保可移植的信任

时间:2009-12-01 20:27 点击:762次 字体:[ ]




信任不可移植的问题

您经常会遇到需要提供个人信息的 Web 站点,原因基本上是验证或者通过个人首选项定制站点。最终,您会发现在许多不同的地方有多个帐户。如果每个站点都为此设立自己的用户资料库,结果就会造成:

  • 对所有这些单独的站点都要考虑您的信息的安全。
  • 多个站点不能协同为您提供所感兴趣的更精细的服务。

为了进一步说明上述第二点,我提供一个很典型的例子:旅游预约。其中包括机票、旅馆和出租车的预定。您可能希望向某家航空公司、某个旅馆以及某个汽车出租商预订,但是不存在一种机制使您能够在三个独立的站点之间无缝移植——可能需要提交证明进行三次验证(假设这三家您都有帐户)。

SAML 被设计成解决这一问题,它允许只有少数经过选择的团体保留您的信息,并且如果需要,在得到您的明确批准之后这些团体可以与其他有关的团体共享这些信息。这意味着,您的信息安全的掌握在您所信任的团体手中,并且可以访问一些供应商通过组织多种低层次服务所提供的高级服务。

本文将说明 SAML 如何实现这一目标。

通行证适用于什么地方?
Microsoft Passport 试图通过一种非常简单的、集中的方式解决这一问题。Microsoft 通行证服务包括一个大型的中心资料库,存储所有主体及其属性。使用这个中心资料库中的信息,各个参与的站点可以允许主体访问信息或者授权执行特定的动作。唯一的问题是——可能很多组织都有同感——他们失去了对主体数据的所有权。SAML 通过联合识别、验证和授权的形式克服了这一问题。验证和授权的联合制允许企业建立自己所有和控制的数据,并能够以结构化的、受控的方式与协作企业共享这些数据。

SAML 的目标

SAML 的主要目标包括:

  • 建立一种独立于协议和平台的验证和授权交换机制(也称为单点登录,或者SSO)。
  • 应该独立部署环境,能够用于集中式的、分散式的以及联合式的部署场景。
  • SAML 框架应该是基于 XML 的。

SAML 的体系结构

SAML 是一种控制对已验证主体的资源进行访问的机制。对资源的访问基于特定的策略管理。这种机制需要两种关键性的活动:

  • 基于策略的访问控制决策。
  • 强制实施这些决策。

SAML 提供了两种角色处理这些活动:策略决策点(Policy Decision Points,PDPs)和策略实施点(Policy Enforcement Points,PEPs)。

场景:主体希望从目标 Web 站点访问一些受保护的内容。主体前往能够识别或者已经验证该主体的源 Web 站点。用户从源站点出发尝试访问目标 Web 站点上的受保护内容,步骤如下:

  1. 主体向源站点验证并请求到目标站点受保护资源的链接。
  2. 源站点使用验证标志重定向主体。
  3. 主体使用该标志向目标站点请求受保护的资源。
  4. 目标站点 PEP 检查该 PDP 的权限。
  5. PDP 可能内部请求源站点使用该标志进行 SAML 验证断言。
  6. 源站点根据标志向目标站点提供 SAML 验证断言。
  7. 目标站点向主体提供受保护的资源。

总之,在源站点验证的主体从 SAML 权威获得一个标志并将其提供给目标站点。目标站点使用该标志从源站点请求所需要的信息而不需要明确地从主体获取。

SAML 综述

SAML 规范由以下部分组成:

  • 断言与协议:该规范处理定义 XML 编码的断言的语法和语义,以及请求和响应协议。
  • 绑定与配置文件:该规范处理 SAML 请求/响应消息到底层通信协议如 SOAP 和 SMTP 的映射。控制在底层通信协议中嵌入和提取 SAML 信息的一组规则称为一个配置文件。
  • 一致性规范:不同的 SAML 实现可能只实现这些规范的一部分。一致性规范设置了一种基本标准,SAML 规范的实现在能够称为一致性实现之前必须满足这一标准。这样有助于提高互操作性和兼容性。
  • 安全和保密的问题:该规范涉及 SAML 体系结构中的安全风险,具体而言就是 SAML 如何应对这些风险以及无法解决的风险。

我将采用问答的形式介绍和 SAML 有关的概念。我将逐个回答以下问题以澄清这些基本概念:

  • 什么是 断言
  • 生产和消费断言?
  • 如何 请求断言,如何发送响应?基本上而言,请求和响应协议是什么?
  • SAML 请求响应协议可以绑定到哪些底层的通信传输 协议
  • 如何向 SOAP 这样的底层通信传输协议中 插入 SAML 断言
  • 什么是 一致性规范,为何需要它?
  • 如果只 实现了标准的子集,也能说该实现是兼容的么?
  • 定义一致性的 粒度级别是什么?
  • 基于 SAML 的系统的 安全风险是什么?

什么是断言?

断言提供主体所执行的验证、主体属性、是否允许主体访问特定资源的授权决策等信息。

一组断言组成一个主体的配置文件。配置文件中的断言可能来自不同的组织。

断言有三种类型:

  • 验证:验证断言处理主体在特定时刻、特定机制下的身份验证。
  • 属性:属性断言提供联系特定属性与给定主体的一种机制。
  • 授权决策:授权决策断言管理给定主体访问资源的权限。

谁生产和消费断言?

SAML 权威生产断言。SAML 权威可进一步划分为验证权威、属性权威或者 PDP。断言的消费者是客户或者 SAML 权威本身。

如何请求断言,如何发出响应?基本上而言,请求和响应协议是什么?

SAML 请求响应协议为发送断言请求和获取响应定义了一种标准消息格式。SAML 请求协议定义的消息格式采用下面的请求类型:

  • SubjectQuery允许使用模式定义新的查询类型,指定一个 SAML 主体。
  • AuthenticationQuery请求一个主体的验证信息。返回验证断言作为响应。
  • AttributeQuery请求主体的属性信息。响应中包括请求者拥有权限的那些属性的属性断言。
  • AuthorizationDecisionQuery进行授权决策。根据请求者提交的证据,该查询决定是否授权该请求者访问受保护的资源。
  • AssertionIDReference根据唯一标识符检索特定的断言。
  • AssertionArtifact根据代表断言的助诊文件检索一个断言。

响应消息格式分别对应请求的类型。

SAML 请求响应协议可以绑定到哪些底层的通信传输协议?

SAML 定义了 SAML 请求和响应消息在标准通信传输协议上的映射。目前只定义了一种绑定,SOAP 上的 SAML。SAML SOAP 绑定描述了 SAML 请求和响应消息交换如何映射到 SOAP 消息交换上。SAML 规范规定任何遵循 SAML 规范的实现必须实现基于 HTTP 的 SOAP 上的 SAML。实现也可以选择实现基于其他传输协议系如 SMTP 或 FTP 的 SOAP 上的 SAML。

如何向 SOAP 这样的底层通信传输协议中插入 SAML 断言?

SAML 规范定义了一组称为配置文件的规则,描述了实现应该如何在底层协议消息中插入、提取和集成断言。比如,SAML 的 SOAP 配置文件描述了如何将 SAML 断言添加到 SOAP 消息、SOAP 头会受到 SAML 断言的什么影响,以及如何在 SOAP 消息中处理 SAML 错误。

SAML 规范中定义了两个配置文件:

  • 浏览器发送配置文件或推式配置文件: SAML 断言在 HTML 表单中上传到浏览器,当用户提交表单时作为 HTTP POST 有效负载传递给目标站点。这种情况下,源站点从目标 Web 站点请求一个标志,后者返回一个授权决策标志。使用这个标志将主体重定向到目标 Web 站点。
  • 浏览器助诊文件(artifact)配置文件或者拉式配置文件:一个 SAML 助诊文件作为 URL 查询字符串的一部分带给目标站点,在返回给源站点时明确地引用一个断言。对目标站点的一些保护内容感兴趣的主体从源站点发送一个标志(SAML 助诊文件),目标站点使用这个标志取得验证/授权信息并决定是否允许访问。

什么是一致性规范,为何需要它?

一致性规范有助于客观地评价 SAML 实现或应用程序对 SAML 规范的一致程度。以下原因使一致性规范很有必要:

  • 确保对一致性和一致性需求有共同的理解。
  • 促进验证和授权信息交换的互操作性。
  • 促进一致性测试开发中的统一性。

如果只实现了标准的子集,也能说该实现是兼容的么?

是的。对于遵循整个规范或者规范子集的 SAML 实现来说,可以说是兼容的。

定义一致性的粒度级别是什么?

SAML 一致性根据应用程序或实现所支持的 SAML 绑定和配置文件来定义。对于支持的每种绑定和配置文件,必须从以下几个方面规定一致性:

  • 应用程序或实现是作为 SAML 消息的生产者、消费者还是兼具两种作用。
  • 应用程序或实现支持哪些断言和陈述。

基于 SAML 的系统的安全风险是什么?

SAML 允许就验证和授权进行陈述,但是没有规定如何进行验证和建立授权。SAML 陈述的消费者必须在信任 SAML 陈述之前确信底层的基础设施。底层的基础设施也必须包括作为客户请求和服务器响应来回传递的有效负载的安全性和机密性。

既然 SAML 是一种多方验证和授权系统,一个 SAML 事务中的合法参与者就有可能是用对其他事务有威胁的信息。

和 SAML 断言有关的风险:断言一旦发出就不在发出者的控制之内了。比如,消费者可能在未定的时期内持续使用断言,或者选择与最初的发出者不知道的第三方共享这些信息。

与 SAML 协议有关的风险:通过要求较低层次上的客户验证、客户发出的请求需要签名,或者限制 SAML 请求只能发给有限的已知方,可以防止拒绝服务攻击(DOS)。

与 SAML 协议绑定(目前只有 SOAP 绑定)有关的风险:

  • 窃听
  • 重放
  • 消息插入
  • 消息删除
  • 消息篡改
  • 中间人

与基于 TLS/SSL 的 HTTP 上的 SOAP 有关的风险: 这种方法只针对单跳提供安全性、机密性和授权。对于多次中转,HTTP 和 TLS/SSL 没有提供足够的安全性。

和 SAML 配置文件(浏览器/助诊文件配置文件和浏览器/POST 配置文件)有关的风险:

  • 窃听
  • 偷窃用户验证信息
  • 偷窃持票人的标志
  • 重放
  • 消息插入
  • 消息删除
  • 消息篡改
  • 中间人

SAML 过程

清单 1 示范了如何使用 SAML 检索关于一个主体的断言。这段代码来自 Verisign 所提供的 SAML 示例实现。(请参阅 参考资料下载源代码和相关文件。)


清单 1. 检索属性断言


Public class SAMLAssertions {
// SAML service provider
// Change it to the SAML service provider url that you are
// trying to connect to
static final String SERVICE_URL =
      "https://pilotpts.verisign.com/vspts/SamlResponder";
// Email of the subject that uniquely identifies it
static final String SUBJECT_EMAIL = "jdoe@tpms.verisign.com";
// Subject password to authenticate the user	
static final String SUBJECT_PASSWORD = "password";
// The keystore to be used for getting the private key and 
// the public key
static final String KEYSTORE_FILE = "saml_sample_keystore";
// Keystore password
static final String STORE_PASS = "changeit";
static final String SIGNER_ALIAS = "pilot_saml_signer";
//	VeriSign attribute naming constants
static final String V_NAME_QUALIFIER = "verisign.com/ams";
static final String V_ATTR_NAMESPACE = 
      "verisign.com/ams/namespace/common";
static final String V_ATTR_EMAIL = 
      "//verisign.com/core/attr/email";
static final String V_ATTR_FIRSTNAME = 
      "//verisign.com/core/attr/first_name";
public static void main(String arg[]) {
NameIdentifier nameId =	
      new NameIdentifier(SUBJECT_EMAIL, V_NAME_QUALIFIER, "");
String[] confMethods = { Identifiers.AUTHN_METHOD_PASSWORD };	
SubjectConfirmation sconf = 
      new SubjectConfirmation(confMethods, SUBJECT_PASSWORD);
Subject subject = new Subject(nameId, sconf);
AttributeDesignator[] reqAttrs = null;
AttributeQuery query = new AttributeQuery(subject, reqAttrs);
AttributeStatementProvider provider = null;
try {	
provider = getAttributeStatementProvider();
} catch (Exception e) {	
// XXX Auto-generated catch block
e.printStackTrace();
}
AttributeStatement[] statements = null;
try {	
statements = provider.processAttributeQuery(query);
} catch (Exception e1) {
// XXX Auto-generated catch block
e1.printStackTrace();
}
if (statements.length == 0) {
System.out.println("No statements returned");
}
for (int i = 0; i < statements.length; i += 1) {	
AttributeStatement statement = statements[i];
Authenticity authenticity = statement.getAuthenticity();
System.out.println(	"Statement "+ (i + 1)+ " authenticity: "
      + authenticity.isAuthentic());
// Print attribute statement	
System.out.println("--- Attribute Statement ---");
System.out.println(  "  Subject: "
      + statement.getSubject().getNameIdentifier().getValue())
// Print attribute values
Attribute[] attrs = statement.getAttributes();
for (int k = 0; k < attrs.length; k += 1) {
Attribute attr = attrs[k];
System.out.println(  "Namespace: " + attr.getAttributeNamespace());
System.out.println(" Name: " + attr.getAttributeName());	
Object[] values = attr.getAttributeValues();
for (int m = 0; m < values.length; m += 1) {	
System.out.println( "	Value: " + values[m].toString());
}
}
}
}
private static AttributeStatementProvider
getAttributeStatementProvider()	throws Exception {
// Read the keystore and get the signing cert/key.
InputStream fileInput = new FileInputStream(KEYSTORE_FILE);
KeyStore keystore = 
      KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(fileInput,STORE_PASS.toCharArray());
PrivateKey key = 
      (PrivateKey) keystore.getKey(
            SIGNER_ALIAS,STORE_PASS.toCharArray());
if (key == null) {
throw new Exception(SIGNER_ALIAS + 
      " key not found in keystore " + KEYSTORE_FILE);
}
Certificate[] certArray = 
      keystore.getCertificateChain(SIGNER_ALIAS);
if (certArray == null) {
throw new Exception(SIGNER_ALIAS + 
      " cert not found in keystore " + KEYSTORE_FILE);
}
X509Certificate[] certs = new X509Certificate[certArray.length];
System.arraycopy(certArray, 0, certs, 0, certs.length);
// Create SOAP assertion provider factory with signing information
SOAPAssertionProviderFactory factory =
      new SOAPAssertionProviderFactory(new URL(SERVICE_URL));
factory.setSigningKey(new RSASigningKey(key));
factory.setVerifyingKey(new RSAVerifyingKey(certs));
return factory.newAttributeStatementProvider();	}
}

清单 1中在 SOAP 协议上查询主体属性的步骤描述如下:

  • 第 1 步: 建立关心其属性的主体。这是通过创建 SubjectIdentifier 并定义 SubjectConfirmation 方法实现的。
  • 第 2 步:使用主体的 e-mail ID 作为主体的唯一标识符。
  • 第 3 步:指定验证用户所使用的方法。清单 1 中使用的是口令验证。
  • 第 4 步:创建 AttributeDesignator 对象,该对象指定了希望检索的属性。在清单 1 中,Verisign 的 SAML 实现把这个数组保留为空值,检索与查询对象相关的所有属性值,这些属性在 AttributeDesignator 数组中指定。
  • 第 5 步:使用主体和 AttributeDesignator 数组创建 AttributeQuery 对象。
  • 第 6 步:使用密钥存储和示例 SAML 服务所运行的服务 URL 创建 AttributeStatementProvider
  • 第 7 步:使用 SOAPAssertionProviderFactory 创建 AttributeStatementProvider 。在创建 AttributeStatementProvider 之前必须向 SOAPAssertionProviderFactory 提供签名密钥和检验密钥。签名密钥是主体的私钥,检验密钥带有附加的证书。
  • 第 8 步:对第 6 步创建的 AttributeStatementProvider 执行第 5 步建立的查询。获得一个 AttributeStatement 对象数组。该数组包含提供程序作为查询结果发送的所有属性的值。迭代陈述中的所有属性以便获得属性值。

结束语

本文考察了 SAML 的目标、体系结构和基本概念。SAML 完成了几件事情,澄清了安全可移植性领域的一些混乱:它定义了表示需要交换的信息的标准机制,定义了交换这类信息的标准。如果您迫切需要提供安全可移植性,您就不能不考虑基于这一计划的安全可移植性产品并采用 SAML 作为标准。



本文地址 : http://www.fengfly.com/plus/view-158803-1.html
标签: 安全 移植 使用 SAML 确保 信任
------分隔线----------------------------
相关文章
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
验证码: