SharePoint 安全性

SharePoint 2010 中基于声明的自定义安全模型

Ivory Feng

实现 Stanko
Shabbir Darugar

下载代码示例

Microsoft SharePoint 2010 引入了一种新的基于声明的身份模型,用于构建声明感知应用程序。 当用户声明感知应用程序,她提供了一组声明作为应用程序的身份。 这些声明使内容更精确的授权。 因此,具有某些属性,如国家/地区代码和部门代码的用户授予访问适当的内容。

实施基于声明的企业级的安全提供了一些有趣的挑战。 我们将探索构建在 SharePoint 中的自定义声明提供程序 (CCP)、 将这与 Microsoft FAST Search Server 2010 for SharePoint 集成、 从用户的角度来看管理启用了索赔的内容和避免某些陷阱的过程。 因为我们这样做,您将学习如何设计和 SharePoint 2010 年实现一种动态的自定义基于声明的安全模型。 我们将使用 Contoso 公司的人力资源门户,ContentWeb,对于我们的示例。

应用程序的概述

Contoso 是 100000 名员工,接近于具有全球性公司,ContentWeb 包含大量内容创作者管理上每周执行每日所需的信息。 在大多数情况下,内容是适用于在一个国家或地区的人员,但不是另一个,但不是另一个,或所有 Contoso 员工的一个处分。 某些内容,但是,是可用于仅一小部分 (如 Vp) 的员工需要的敏感数据。

若要覆盖此类广泛的访问群体,请 ContentWeb 使用 SharePoint 组 (SPGs) 与自定义声明显式安全和目标内容。 Contoso 的需要特定的索赔是存储在数据库中,用于定义用户的报销申请"集"。它是此组的索赔确定员工的可以并不能看到的。 管理接口允许信息工作者的支持门户的更改或增加自己的索赔集,使它们能够查看其他用户作为门户。 此功能强大的自定义功能被称为视图门户作为 (VPA)。

ContentWeb 使用基于声明的 Windows 身份验证在 SharePoint 2010 和快速搜索服务器 2010年的 SharePoint 作为联合的企业搜索环境中的搜索引擎。

CCP 的原因?

当用户登录到 ContentWeb 时,基于声明的 Windows 身份验证提供了一组从活动目录,它将作为标识提供程序的声明。 但是,这些单独的索赔不足够的 ContentWeb 来保护和目标内容。 ContentWeb 要求如 SAP) 构建一个完整的报销申请集描述了用户的企业数据存储库中的其他用户信息。 因此,我们需要扩充索赔 CCP。 我们使用这些自定义声明显式安全和将内容指向用户。

具有 CCP 让确定 Contoso 什么报销申请类型和值它想用来描述员工、 供应商和其他人用工作。 此模型是可扩展 ; 它允许 Contoso 可以有效地更改其业务的变化随着时间的推移。

因为您不能方便地编辑来自 Active Directory 的声明,您还需要支持 VPA CCP。 VPA 主要用于获得授权的人员 (用户 A) 想要查看门户作为另一个人 (用户 B) 时。 在这种情况下,自定义声明提供程序添加用户 B 的自定义声明为用户 A 的报销申请集,因此授权用户查看内容可以访问用户 B 的 A。

用户拥有的声明是特性,它们表示"配置文件"。用户可以具有简单和复合索赔。 简单的索赔,如国家/地区代码和用户类型,可以很容易地理解。 ContentWeb 使用一组预定义的简单的索赔 — — 或者,更准确地说,简单的声明类型。 但是,有时员工需要获得具有多个报销申请类型 ; 内容的权限 例如,国家/地区代码 = 用户我们和类型 = FullTimeEmployee — AND 条件。 在这种情况下,您可以创建复合索赔。

现成的 SharePoint 2010 计算中使用 OR 逻辑只设置的用户的声明的声明。 这意味着 SharePoint 2010 支持的 OR 条件将安全和目标,并不总是足够。 让我们看一个示例。 ContentWeb 有国家/地区代码声明和用户类型声明。 它需要为全职美国加强保护某些内容 使用国家/地区代码的员工 = 用户我们和类型 = FullTimeEmployee。 我们不能满足此要求,直接在 SharePoint 2010 使用简单的索赔国家/地区代码或用户类型,因此我们需要创建复合理赔代表使用这两个声明中。

我们无法为全职美国创建新的报销申请类型 员工。 但是,如果公司在其他国家/地区中创建新的办公室,我们再需要更新我们 CCP 的源代码中添加相应的声明类型。 显然,这种方法可能成本高昂而且非常耗时。 此外,ContentWeb 业务团队希望能够添加和移除复合声明类型,而无需新的应用程序版本每次。 正如您所见,ContentWeb 将需要一种动态的、 可扩展的安全模型。

我们如何将管理的所有索赔数据? 我们将使用名为 ContentWebAdminDB 的数据库来存储报销申请元数据。 ContentWebAdminDB 是索赔源后端 ; 它整合了 SAP 和其他企业数据库中的所有索赔源数据。 我们将深入探讨更多的位此数据库。 然后,我们将使用普通 ASP。NET 的管理应用程序调用 ContentWebAdmin 以连接到此数据库来创建和更新复合索赔元数据和 VPA 配置。 (此应用程序的详细信息是超出了本文的范围。使用简单的索赔会创建复合声明。 例如,在 ContentWebAdmin 应用程序中我们可以创建称为美国 FullTimeEmployee 使用国家/地区代码的复合理赔 = 美国和用户类型 = FullTimeEmployee 简单的索赔。 与此 coumpound 报销申请的元数据,任何用户都有国家/地区代码 = 美国和用户类型 = FullTimeEmployee 简单的索赔,新的复合声明美国 FullTimeEmployee = true 将添加到用户的声明集。 注意没有复合声称美国 FullTimeEmployee = 假出现在任何用户的报销申请集中。 使用动态复合声明此设计中,每个用户只有少数几十个索赔的总尽管具有复合索赔的排列可能相当高。 这是确保良好性能的关键。

当用户登录到 ContentWeb 时,将调用 CCP。 CCP 调用自定义存储的过程时,sp_GetUserClaims,同时在用户的标识声明中传递的 ContentWebAdminDB 中。 该存储的过程将检查 VPA 配置,并为该用户的所有简单和复合索赔回到 CCP。 正如您所见,动态复合索赔不是动态的授权规则相同。 我们的解决方案不会更改的方式 SharePoint 2010 的复合索赔计算索赔。 我们只需将复合索赔注入用户声明集基于复合索赔的元数据配置。 图 1 显示了 ContentWeb 的高级概述。

A High-Level View of ContentWeb
图 1 A ContentWeb 的高级视图

内 ContentWeb 自定义声明提供程序

ContentWeb CCP 具有特殊 Microsoft.SharePoint.Administration.SPClaimProvider 从继承的类。 图 2 显示了此类的一部分。 请注意 (其中设置显示文本属性) 的代码的第 16 行。 我们添加它有助于使我们的自定义声明类型和值显示更用户友好且可读的方式。

图 2 使索赔更易阅读

protected override void FillResolve(
  Uri context, string[] entityTypes, SPClaim resolveInput,
  List<Microsoft.SharePoint.WebControls.PickerEntity> resolved)
{
  string claimTypeName = string.Empty;
  string claimValue = string.Empty;
 
  // Handles only ContentWeb claim types
  if (null != resolveInput && resolveInput.ClaimType.Contains(
    ContentWebClaimTypes.ContentWebClaimTypePrefix))
  {
    claimValue = resolveInput.Value.ToLower();
    claimTypeName = GetName(resolveInput.ClaimType);
 
    PickerEntity entity = CreatePickerEntity();
    entity.Claim = resolveInput;
    entity.Description = resolveInput.ClaimType + " = " + claimValue;
    entity.DisplayText = claimTypeName + " = " + claimValue;
    entity.EntityData[PeopleEditorEntityDataKeys.DisplayName] =
      claimTypeName + " = " + claimValue;
    entity.EntityType = SPClaimEntityTypes.User;
    entity.IsResolved = true;
    resolved.Add(entity);
  }
}

ContentWeb CCP 需要向用户提出要求,在 ContentWebAdminDB 中调用存储的过程的连接字符串。 CCP 是服务器场级功能,因为它不是任何 Web 应用程序中,范围内因此我们不能使用 web.config 文件来配置数据库连接字符串。 我们可以使用 machine.config,但因为我们有多个 Web 前端,这是不理想。 相反,我们将使用 SharePoint 分层对象存储区,SPPersistedObject,来存储数据库连接字符串。 这存储在 SharePoint 配置数据库中,在 SharePoint 服务器场中进行的数据库连接字符串可用于所有 Web 前端。

内 ContentWeb CCP,我们创建一个类的继承 Microsoft.SharePoint.Administration.SPPersistedObject,如中所示图 3

图 3 ConnectionStringStorage 类

[Guid("56705e15-abd3-44f0-adea-91488da1a572")]
public class ConnectionStringStorage
  : Microsoft.SharePoint.Administration.SPPersistedObject
{
    [Persisted]
    private string m_connectionString;
 
    public ConnectionStringStorage()
    {
    }
 
    public ConnectionStringStorage(
      string name, SPPersistedObject parent)
      : base(name, parent)
    {
    }
 
    public ConnectionStringStorage(
      string name, SPPersistedObject parent, Guid guid)
      : base(name, parent, guid)
    {
    }
 
    public string ConnectionString
    {
      get { return m_connectionString; }
      set { m_connectionString = value; }
    }
}

我们将使用下面的 Windows PowerShell 脚本来注册的数据库连接字符串:

[System.Reflection.Assembly]::LoadWithPartialName(
  "Microsoft.Sample.ContentWeb.ClaimsSecurity")
$id = new-object System.Guid("56705e15-abd3-44f0-adea-91488da1a572")
$farm = Get-SPFarm
$existingObject = $farm.GetObject($id)
$existingObject.Delete()
$newObject =
  new-object Microsoft.Sample.Contoso.ClaimsSecurity.ConnectionStringStorage(
  "ConnectionString", $farm, $id)
$newObject.ConnectionString = "Data Source=ContentWebAdminSQLServer;
  Initial Catalog=ContentWebAdminDB;Integrated Security=True;Timeout=30"
$newObject.Update();
Iisreset

正如您所见,我们引用 CCP dll。 我们创建一个新的 ConnectionStringStorage 对象,并将其连接字符串属性设置。 最后,我们调用其更新的方法将其保存到 SharePoint 配置数据库。

我们建议的连接字符串超时值小于 60 秒。 CCP 有 60 秒执行默认超时期限。 这意味着如果数据库连接超时,您必须捕获从连接字符串,而不是一个令人误解 CCP 执行从真实异常的能力。

内部 CCP 的构造函数中,我们将检索连接字符串,并将其存储在模块级变量中:

public class ContentWebClaimProvider : SPClaimProvider
{
  private static string connectionString = null;
 
  public ContentWebClaimProvider(string displayName)
    : base(displayName)
  {
    Guid guid = new Guid(@"56705e15-abd3-44f0-adea-91488da1a572");
    ConnectionStringStorage storage =
      (ConnectionStringStorage)SPFarm.Local.GetObject(guid);
    connectionString = storage.ConnectionString;
  }
}

我们希望能够跟踪当 CCP 连接到数据库的用户索赔。 SharePoint 2010 具有此严苛的新功能。 它调用的 Microsoft.SharePoint.Utilities.SPMonitoredScope 对象,,它会监视性能和用于指定代码块的资源。 下面的代码记录 CCP 的数据库调用:

using (new SPMonitoredScope("ContentWeb.CCP.GetUserClaims", 5))
{
  userClaimsDataSet = CustomClaimSourceDA.GetUserClaims(
    userAlias, connectionString);
}

我们还可以配置在 SharePoint 管理中心的事件级别和此事件的跟踪级别。 这些都由在监视下的 SharePoint 基础类别中的监视对象 |报告 |配置诊断日志记录。

在 ContentWebAdminDB 数据库内

前面已提到,ContentWebAdminDB 将整合 SAP 和其他企业数据库,请从用户的报销申请数据,它包含自定义声明源。 ContentWeb CCP 调用存储的过程时,sp_GetUserClaims,检索用户的自定义声明。

ContentWebAdmin 应用程序允许用户配置复合索赔和 VPA 经授权的用户。 ContentWebAdminDB 存储复合索赔配置元数据和 VPA 配置表中。 当 ContentWeb CCP 调用 sp_GetUserClaims 时,此存储的过程将检查 VPA 配置并再返回简单的索赔和复合索赔。 详细的设计和实施此数据库的超出了本文的范围。 然而,我们还包括可下载的代码包中的硬编码声明值与虚拟 sp_GetUserClaims 存储过程的 SQL 脚本。

使用 SharePoint 组

SPG 是 SharePoint 用户的逻辑包装。 这是为 ContentWeb,使用数百个复合的声明很方便。 没有 SPGs,它将是非常困难,以待内容作者管理所有的索赔。

使用 SPGs 提供了以下好处:

  • 友好命名: SPGs 允许用户创建可能含义模糊的声明值为友好和有意义的组名称。 例如,ContentWeb 具有名为"我们 FullTime 雇员"描述具有报销申请的用户的 SPG 值国家 = 美国,CompanyCode = 1010年和 UserSubType = FTE。
  • 人员选取器名称解析支持: SharePoint 2010 年人员选取器控件以本机方式支持名称解析为 SPGs。 这便于更方便地查找和选择 SPGs,如中所示图 4

SharePoint Groups in People Picker
图 4 SharePoint 组人员选取器中

  • 动态的报销申请安全管理: 假设您需要更改"我们 FullTime 雇员,"添加用户类型的定义的其他属性 = Corp — 国家 = 美国,CompanyCode = 1010年和 UserSubType = FTE — 由于不断变化的业务需要。 很容易地进行更改,只是该一个 SPG 和保护,因为 SPG 将自动继承此更改的所有对象中。
  • 为保护和目标内容只是一个 SPG: SharePoint 2010 现在支持安全和面向对象使用相同的 SPG 的能力。 这就消除了与创建访问群体,导入用户配置文件,运行的配置文件同步作业等目标相关的典型开销。
  • 一个 SPG 与索赔相关的多个: 假设您需要为其级别的范围从 60 到 65 的全职员工安全页。 您可以轻松地执行此操作通过创建具有 compund 索赔 UserSubType SPG = FTE 和 Level = 60,UserSubType = FTE 和 Level = 61…UserSubType = FTE 和 Level = 65。 SharePoint 2010 解释所有作为这些索赔的"OR"。

管理许多 SPGs 有可能会非常耗时、 繁琐而且容易出错。 ContentWeb 业务团队使用 Excel 文件来管理数百个具有关联的自定义声明的组。

没有为自动创建的 SPGs 的各种选项。 我们创建了 Windows PowerShell 脚本来从 XML 文件来实现自动读取数据。 (您会发现此脚本在代码下载中,可以从下载 code.msdn.microsoft.com/mag201111SPSecurity。)我们填充使用业务团队的 Excel 文件的 XML 数据文件。 图 5 显示了示例 XML 配置文件。

图 5 示例 XML 配置文件

<?xml version="1.0" encoding="utf-8"?>
<SharePointGroups url="http://contentweb" owner="contoso\ivfeng" >
  <SharePointGroup name="ContentWeb-FTE"
    description="ContentWeb-FTE" permissionLevel="Read">
    <Claim type="UserType" value="emp"/>
  </SharePointGroup>
  <SharePointGroup name="ContentWeb_US_0000_Emp_Corp_HRPro"
    description="ContentWeb_US_0000_Emp_Corp_HRPro">
    <Claim type="CompoundClaim" value="US+emp+corp+hrpro"/>
  </SharePointGroup>
  <SharePointGroup name="ContentWeb_US_0000_Emp_Corp_Manager"
     description="ContentWeb_US_0000_Emp_Corp_Manager">
    <Claim type="CompoundClaim" value="us+emp+corp+manager"/>
    <Claim type="CompoundClaim" value="US+emp+corp+hrpro"/>
  </SharePointGroup>
</SharePointGroups>

使用 SPGs 到目标

若要使用目标,您需要为 Web 应用程序启用用户配置文件服务应用程序。

没有要提防针对使用 SPGs 时的一个棘手问题。 最初,我们发现 SPGs 包含 Active Directory 用户或安全组的所有工作正常,但包含自定义声明用户 SPGs 不起根本作用。 这些组的权限级别相关的根本原因。 当我们使用自定义声明创建的 SPGs 时,我们不想分配任何默认权限级别。 但是,如果 SPG 未分配的访问权限级别创建和更高版本用于安全时,它将标记具有特殊的权限级别称为有限的访问权限,如中所示图 6

A SharePoint Group with Limited Access
图 6 SharePoint 组具有有限访问权限

ContentWeb 拥有数百名的 SPGs 和其中的大多数只用于目标访问群体,因为它们没有任何权限级别设置。 但是,目标访问群体处理器不能在这些 SPGs,而无需任何权限级别中拉出。 我们幸运,发现,我们已将其应用于目标访问群体页的权限用户界面通过一种解决方法。 我们正在使用对于目标访问群体,然后立即 SPGs 权撤消此权限授予"读取"。 该进程使 SharePoint 来标记这些 SPGs 具有有限的访问权限级别,并将目标读者高兴地尊重该权限级别。 请注意您不必经过此授予和撤消的 SPGs 多次的过程,这一点至关重要。 您需要在安全性继承树内只需一次完成它。 注意如果您断开安全性继承,您需要再次,执行该即使您已经在父级别完成它。

实现搜索 ContentWeb

我们与该应用程序的主要目标之一就是改善 Contoso 员工的搜索体验。 我们希望 ContentWeb,以使内容比其原来在过去得更加明显。

为 ContentWeb,可以执行此操作,我们在联合环境中承载 SharePoint 使用快速搜索服务器 2010年。 请返回参阅图 1 为 Contoso 的联盟快速搜索环境。 这显示了称为快速搜索联盟场 SharePoint 服务器场。 此服务器场的后面是 Microsoft 快速搜索服务器 SharePoint 引擎和数据库。 快速搜索场包含所有查询搜索服务应用程序 (查询 Ssa) 和内容的 SSA。

自然,我们创建了一个现有的内容 SSA 中的内容源。 (快速搜索服务器建议只有一个内容 SSA)。完成后,内容 SSA 将爬网 ContentWeb 内容数据库,并对 ContentWeb 和其他 intranet 应用程序进行搜索索引可用。

然后,我们将创建单独的查询 SSA 和它发布到 ContentWeb。 与在 ContentWeb 上的初始搜索测试,我们发现基本搜索工作正常,但搜索安全修整未按预期方式工作。 对于 ContentWeb 自定义声明的保护任何页面,用户无法即使它们拥有的安全权限不到搜索结果中的链接。 我们终于想出我们需要具有自定义声明类型映射注册中搜索安全修整工作的快速搜索 SharePoint 场 ContentWeb。 要这样做的最简单方法是到快速搜索 SharePoint 服务器场部署 CCP。 不仅我们未有确认报销申请类型映射进行了注册,我们还必须确保所有声明 Id (帐户中所示的图 7) 都相同的多个相同的报销申请类型值对所有 SharePoint 场。

Claim IDs
图 7 报销申请 Id

目前,即使使用 SharePoint 2010 年 6 月 2011年累积更新,声称是不可变的 SharePoint 2010 年的类型映射。 一旦 CCP 部署 SharePoint 2010 场上,声明类型映射注册,并保持不变,即使您删除并重新部署 CCP。 您可能会对多个 SharePoint 场 CCPs,因为它是非常重要您将部署所有 CCPs 以确保报销申请的相同顺序 Id 都互不相同跨所有服务器场。 如果您不这样做,将不对齐序列 Id 和搜索不返回精确的结果。

当 ContentWeb 内容进行爬网时,将不会调用 CCP。 所需的全部是在快速搜索服务器场中注册,以便爬网程序引擎可以解码 ContentWeb 自定义声明的报销申请类型映射。 然后,它将搜索索引中存储已解码的自定义声明的安全。 删除 ContentWeb CCP 是可选的因为声明类型映射将保留。 此外,我们完全不需要 ContentWeb CCP 来增加对快速搜索服务器场的用户提出要求。

安全修整搜索结果: Contoso Intranet 门户

为了为可搜索其他 Contoso intranet 门户网站的 ContentWeb 内容,您需要确保以下:

  • 需要显现的 ContentWeb 内容的所有 intranet 门户必须基于 SharePoint 2010,并且是基于声明的 Web 应用程序使用 Windows 身份验证。
  • 所有 intranet 门户必须都查询相同的快速搜索索引。
  • 所有 intranet 门户必须都具有 ContentWeb CCP 安装在其上。 (如果有多个 CCP,它们都必须安装以确保的理赔对齐 Id 相同的顺序。)

如果所有这些条件都满足,跨所有 Contoso intranet 门户都将可搜索 ContentWeb 内容。

总结

SharePoint 2010 强的集成提供了基于声明的安全。 SharePoint 组、 索赔和自定义声明提供商允许您授权企业广泛以及细粒度级别上的内容。 正如您所见,您可以相对轻松地满足许多方案。

这种设计还使开发人员能够生成改变他们的主张,并查看站点作为其他用户,然后再还原允许 (如技术支持人员) 的信息工作者的强大工具。

与大多数新的设计实现,我们的经验不是有"机会了解,"但最终产品很值得。 我们提供了示例代码应该可以帮助让您执行正确的发展方向和关闭到部署您的下一代企业门户上的一个良好的开端!

Jinhui (Ivory) Feng 是高级软件开发工程师在 Microsoft 从事其内部的人力资源应用程序。

Shabbir Darugar 是高级软件开发工程师和项目领导在 Microsoft 从事其内部的人力资源应用程序。

实现 Stanko 是一个潜在顾客程序管理器,在 Microsoft 从事其内部的人力资源应用程序。

这要归功于以下技术专家审阅这篇文章: Tom Wisnowski