声明演练:为 SharePoint 2010 的基于表单的身份验证 Web 应用程序创建声明提供程序

**摘要:**了解如何为 Microsoft SharePoint 2010 基于表单的身份验证 Web 应用程序创建声明提供程序。

上次修改时间: 2015年3月9日

适用范围: Business Connectivity Services | Open XML | SharePoint Designer 2010 | SharePoint Foundation 2010 | SharePoint Online | SharePoint Server 2010 | Visual Studio

本文内容
为基于表单的身份验证 Web 应用程序创建声明提供程序的概述
方案:使用声明访问 SharePoint 资源
结论
附录 A:标识声明编码字符映射
其他资源

**供稿人:**Andy Li,Microsoft Corporation

目录

  • 为基于表单的身份验证 Web 应用程序创建声明提供程序的概述

  • 方案:使用声明访问 SharePoint 资源

  • 结论

  • 附录 A:标识声明编码字符映射

  • 其他资源

单击以获取代码 下载代码:ClaimsExample-ContosoClaimsProviders(该链接可能指向英文页面)

为基于表单的身份验证 Web 应用程序创建声明提供程序的概述

在此演练中,为在声明演练:使用自定义成员资格和角色提供程序为基于声明的 SharePoint 2010 Web 应用程序创建基于表单的身份验证中创建的基于表单的 Web 应用程序,实现一个示例客户关系管理 (CRM) 声明提供程序。然后,修改此声明提供程序以提供附加 CRM 声明(通过使用声明扩充),可通过访问控制列表 (ACL) 使用这些附加声明控制对 SharePoint 资源的访问。

默认情况下,声明搜索和解析使用成员身份和角色提供程序,这些提供程序实现 Microsoft SharePoint Foundation 2010 和 Microsoft SharePoint Server 2010 从基于表单的身份验证的默认声明提供程序调用的接口。可能在有些情况下需要其他声明(例如,对于方案部分描述的 CRM)。在这类情况下,可以使用扩充声明提供程序。

术语声明扩充 适用于任何类型的声明身份验证:Windows 声明身份验证、安全声明标记语言 (SAML) 登录和基于表单的身份验证。

备注

有关声明扩充的详细信息,请参阅声明演练:编写 SharePoint 2010 的声明提供程序

方案:使用声明访问 SharePoint 资源

假定您有一个包含一组完全不同的帐户设置的外部 CRM 系统。登录 CRM 系统时,用户提供一组不同的用户名和密码。登录后,CRM 系统将基于用户帐户设置授予每个用户不同的权限。

例如,每个 CRM 帐户均具有 Role 和 Region 这两个属性。Role 属性指示当前用户是销售代表、销售经理还是主管人员。Region 属性指示用户所在的位置。

在 Microsoft SharePoint 2010 中,存在一个网站集用来存储与 CRM 相关的文档。我们的想法是,在某个用户登录 SharePoint 网站时,我们可以从 CRM 系统获得该用户的角色和区域信息,以便我们能够基于其 CRM 角色和区域信息,强制实施文档权限。

步骤 1:准备项目

首先,准备 SharePoint 项目。

准备项目

  1. 创建一个空的 SharePoint 项目。

  2. 将此项目命名为 ContosoClaimProviders。

  3. 要求您提供 SharePoint 网站进行调试时,请键入 http://intranet.contoso.com:200。这是您已启用基于表单的身份验证声明的位置。

  4. 添加对 Microsoft.IdentityModel.dll 程序集的引用。

步骤 2:添加用户查找函数

接下来,添加一个用于查找用户信息的函数。

添加用户查找函数

  1. 将一个名为 CRMClaimTypes.cs 的类文件添加到项目中。

  2. 添加以下命名空间。

    using Microsoft.SharePoint.Administration;
    using Microsoft.IdentityModel.Claims;
    using System.Collections;
    
  3. 将 CRMClaimTypes.cs 文件中的代码替换为以下代码。CRMClaimType 类定义两个我们的声明提供程序支持的自定义声明。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ContosoClaimProviders
    {
        public class CRMClaimType
        {
            public static string Role = "http://schemas.sample.org/ws/2009/12/identity/claims/CRMRole";
            public static string Region = "http://schemas.sample.org/ws/2009/12/identity/claims/CRMRegion";
        }
    }
    
  4. 添加一个名为 CRMUserInfo.cs 的类文件。CRMUseInfo 类为用户信息查找提供支持。下面提供的代码仅用于演示目的。生产实现应考虑将用户信息存储在安全位置,或从目录服务或数据库查找数据。

    1. 将以下代码添加到 CRMUseInfo 类中。

              private static string[] userDB = 
                 {
                  "bob:CRMRole:Reader", 
                  "bob:CRMRole:SalesRepresentative",
                  "bob:CRMRegion:Northwest",
                  "mary:CRMRole:Reader",
                  "mary:CRMRole:SalesManager",
                  "mary:CRMRegion:East",
                  "jack:CRMRole:Reader",
                  "jack:CRMRole:Executive",
                  "jack:CRMRegion:East",
                  "admin1:CRMRole:Administrator",
                  "contoso\\andy:CRMRole:SalesManager",
                   contoso\\administrator:CRMRole:SalesManager
                 };
      
              private static string[] claimsDB = 
                 {"CRMRole:Reader", 
                  "CRMRole:SalesRepresentative",
                  "CRMRole:SalesManager",
                  "CRMRole:Executive",
                  "CRMRole:Administrator",
                  "CRMRegion:Northwest",
                  "CRMRegion:East",
                  };
      
    2. 添加一个名为 GetClaimsForUser 的静态方法。这是一个可返回特定用户的所有声明的实用程序方法。

              public static List<Claim> GetClaimsForUser(string username)
              {
                   List<Claim> userClaims = new List<Claim>();
                  foreach(string userInfo in userDB)
                  {
                      string[] claims = userInfo.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries);
                      if (username == claims[0])
                      {
                          userClaims.Add(new Claim(GetClaimTypeForRole(claims[1]), claims[2], Microsoft.IdentityModel.Claims.ClaimValueTypes.String));
                      }
                  }
      
                  return userClaims;
              }
      
    3. 添加一个名为 GetAllUsers 的静态方法。这是另一个可返回用户的所有帐户名称的实用程序方法。

              // Manually constructs a list of users. In a real-world 
              // production environment, you should look up a directory service
              // or database to retrieve the user information.
              public static List<string> GetAllUsers()
              {
                  List<string> allUsers = new List<string>();
      
                  // Add forms users.
                  allUsers.Add("bob");
                  allUsers.Add("mary");
                  allUsers.Add("jack");
                  allUsers.Add("admin1");
      
                  // Add Windows domain user if you want this provider
                  // to augment the claims.
                  allUsers.Add("contoso\\andy");
                  return allUsers;
              }
      
    4. 将以下两种方法添加到 CRMUserInfo 类。

      GetAllClaims 方法返回此提供程序支持的所有已知声明值。所有值都在 claimsDB 字符串数组中定义。

      GetClaimTypeForRole 实用程序方法将声明类型从其字符串名称转换为实际声明类型。例如,CRMRole 转换为 http://schemas.sample.org/ws/2009/12/identity/claims/CRMRole。

              /// <summary>
              /// This method returns all the known claims from the CRM system  
              /// so that the claims provider is able to search and resolve 
              /// the claims in People Picker.
              /// </summary>
              /// <returns></returns>
              public static Hashtable GetAllClaims()
              {
                  Hashtable knownClaims = new Hashtable();
                  foreach(string claimItem in claimsDB)
                  {
                      string[] claim = claimItem.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries);
                      knownClaims.Add(claim[1].ToLower(), claim[0].ToLower());
                  }
                  return knownClaims;
              }
      
      
              public static string GetClaimTypeForRole(string roleName)
              {
                  if (roleName.Equals("CRMRole", StringComparison.OrdinalIgnoreCase))
                      return CRMClaimType.Role;
                  else if (roleName.Equals("CRMRegion", StringComparison.OrdinalIgnoreCase))
                      return CRMClaimType.Region;
                  else
                      throw new Exception("CRM claim type not found!");
              }
      

步骤 3:创建声明提供程序

接下来,实现声明提供程序。

实现声明提供程序

  1. 添加一个名为 CRMClaimProvider.cs 的类文件。

  2. 添加以下命名空间。

    using Microsoft.SharePoint.Administration.Claims;
    using Microsoft.IdentityModel.Claims;
    using System.Collections;
    using Microsoft.SharePoint.WebControls;
    
  3. 将 CRMClaimProvider 类的继承修改为 SPClaimProvider 类。

    public class CRMClaimProvider : SPClaimProvider
    
  4. 添加以下代码以支持 Name 属性的构造。

            public CRMClaimProvider(string displayName)
                : base(displayName)
            {
            }
    
            public override string Name
            {
                get { return "ContosoCRMClaimProvider"; }
            }
    
  5. 将以下代码添加到此类。如属性名称所示,这些属性返回 true 或 false 来支持每个特定方法。

    备注

    有关如何实现层次结构的示例,请参阅声明演练:编写 SharePoint 2010 的声明提供程序

           /// <summary>
            /// Return true if you are doing claims augmentation.
            /// </summary>
            public override bool SupportsEntityInformation
            {
                get { return true; }
            }
    
            /// <summary>
            /// Return true if you support claims resolution in the People Picker.
            /// </summary>
            public override bool SupportsResolve
            {
                get { return true; }
            }
    
            /// <summary>
            /// Return true if you support claims search in the People Picker.
            /// </summary>
            public override bool SupportsSearch
            {
                get { return true; }
            }
    
            /// <summary>
            /// Return true if you support hierarchy display in the People Picker.
            /// </summary>
            public override bool SupportsHierarchy
            {
                get { return false; }
            }
    
                    public override bool SupportsUserSpecificHierarchy
            {
                get
                {
                    return base.SupportsUserSpecificHierarchy;
                }
            }
    
  6. 将以下方法添加到此类:

    • FillClaimTypes   由 SharePoint 2010 调用来检索声明提供程序支持的声明类型。

    • FillClaimValueTypes   由 SharePoint 2010 调用来检索其支持的每个声明类型对应的声明值类型。

    • FillSchema   由人员选取器调用来获取可在人员选取器上显示的信息。

    • FillEntityTypes   告知人员选取器声明提供程序支持的声明类型(即用户或角色)。

            /// <summary>
            /// Returns all the claim types that are supported by 
            /// this claims provider.
            /// </summary>
            /// <param name="claimTypes"></param>
            protected override void FillClaimTypes(List<string> claimTypes)
            {
                if (null == claimTypes)
                {
                    throw new ArgumentNullException("claimTypes");
                }
    
                // Add the claim types that will be added by this claims provider.  
                claimTypes.Add(CRMClaimType.Role);
                claimTypes.Add(CRMClaimType.Region);
            }
    
            /// <summary>
            /// Return all the claim value types that correspond to the claim  
            /// types. You must return the values in the same order as 
            /// in the FillClaimTypes method. 
            /// </summary>
            /// <param name="claimValueTypes"></param>
            protected override void FillClaimValueTypes(List<string> claimValueTypes)
            {
    
                if (null == claimValueTypes)
                {
                    throw new ArgumentNullException("claimValueTypes");
                }
    
                claimValueTypes.Add(Microsoft.IdentityModel.Claims.ClaimValueTypes.String);
                claimValueTypes.Add(Microsoft.IdentityModel.Claims.ClaimValueTypes.String);
            }
    
            /// <summary>
            /// Required for People Picker. This tells the People Picker what 
            /// information is available for the entity.
            /// </summary>
            /// <param name="schema"></param>
            protected override void FillSchema(SPProviderSchema schema)
            {
                schema.AddSchemaElement(new SPSchemaElement(PeopleEditorEntityDataKeys.DisplayName,
                                                            "DisplayName",
                                                             SPSchemaElementType.TableViewOnly));
            }
    
            /// <summary>
            /// Returns the entity type for the claims that are returned from the 
            /// claims provider.
            /// </summary>
            /// <param name="entityTypes"></param>
            protected override void FillEntityTypes(List<string> entityTypes)
            {
                entityTypes.Add(SPClaimEntityTypes.FormsRole);
                entityTypes.Add(SPClaimEntityTypes.FormsRole);
            }
    
  7. 添加 FillClaimsForEntity 方法以支持声明扩充。在对用户进行身份验证后,此方法由 SharePoint 安全令牌服务 (STS) 调用。

          /// <summary>
            /// Implement this method if the claims provider supports
            /// claims augmentation.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="entity"></param>
            /// <param name="claims"></param>
            protected override void FillClaimsForEntity(Uri context, SPClaim entity, List<SPClaim> claims)
            {
                if (null == entity)
                {
                    throw new ArgumentNullException("entity");
                }
                if (null == claims)
                {
                    throw new ArgumentNullException("claims");
                }
    
                // Add the role claim.
                SPClaim userIdClaim = SPClaimProviderManager.DecodeUserIdentifierClaim(entity);
    
                // Add claims for users.
                List<string> allCRMUsers = CRMUserInfo.GetAllUsers();
    
                if(allCRMUsers.Contains(userIdClaim.Value.ToLower()))
                {
                    List<Claim> userClaims = CRMUserInfo.GetClaimsForUser(userIdClaim.Value.ToLower());
                    foreach(Claim claim in userClaims)
                    {
                        claims.Add(CreateClaim(claim.ClaimType, claim.Value, claim.ValueType));
                    }
    
                }
    
            }
    
  8. 添加 FillSearch 方法以支持搜索声明。

           /// <summary>
            /// Required if you implement the claims search in the People Picker.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="entityTypes"></param>
            /// <param name="searchPattern"></param>
            /// <param name="hierarchyNodeID"></param>
            /// <param name="maxCount"></param>
            /// <param name="searchTree"></param>
            protected override void FillSearch(Uri context, string[] entityTypes, string searchPattern, string hierarchyNodeID, int maxCount, SPProviderHierarchyTree searchTree)
            {
                string keyword = searchPattern.ToLower();
                Hashtable knownClaims = CRMUserInfo.GetAllClaims();
                List<string> knownClaimsList = new List<string>();
    
                // Convert the knownClaims.Key into a List<string> for LINQ query.
                foreach (string claim in knownClaims.Keys)
                {
                    knownClaimsList.Add(claim);
                }
    
    
                var claimQuery = knownClaimsList.Where(claim => claim.IndexOf(keyword) >= 0).Select(claim => claim);
    
                foreach (string claimValue in claimQuery)
                {
                    // Get the ClaimType for the claim type.
                    // For example, if you search "SalesManager", 
                    // the ClaimType will be CRMClaimType.Role.
    
                    string claimType = CRMUserInfo.GetClaimTypeForRole((string)knownClaims[claimValue]);
    
                    PickerEntity entity = CreatePickerEntity();
                    entity.Claim = CreateClaim(claimType, claimValue, Microsoft.IdentityModel.Claims.ClaimValueTypes.String);
                    entity.Description = claimValue;
                    entity.DisplayText = claimValue;
                    entity.EntityData[PeopleEditorEntityDataKeys.DisplayName] = claimValue;
                    entity.EntityType = SPClaimEntityTypes.FormsRole;
                    entity.IsResolved = true;
                    searchTree.AddEntity(entity);
                }
    
            }
    
  9. 添加以下两个 FillResolve 方法以支持人员选取器中的声明解析。

            /// <summary>
            /// Resolve a single claim by using exact match. This method is required
            /// for claim search and for claim resolve.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="entityTypes"></param>
            /// <param name="resolveInput"></param>
            /// <param name="resolved"></param>
            protected override void FillResolve(Uri context, string[] entityTypes, SPClaim resolveInput, List<PickerEntity> resolved)
            {
                string keyword = resolveInput.Value.ToLower();
                Hashtable knownClaims = CRMUserInfo.GetAllClaims();
    
                if (knownClaims.ContainsKey(keyword))
                {
    
                    // Get the ClaimType for the claim type.
                    // For example, if you search "SalesManager", 
                    // the ClaimType will be CRMClaimType.Role.
                    // In this case, the keyword is the value of the claim.
                    string claimValue = keyword;
                    string claimType = CRMUserInfo.GetClaimTypeForRole((string)knownClaims[keyword]);
    
                    PickerEntity entity = CreatePickerEntity();
                    entity.Claim = CreateClaim(claimType, claimValue, Microsoft.IdentityModel.Claims.ClaimValueTypes.String);
                    entity.Description = claimValue;
                    entity.DisplayText = claimValue;
                    entity.EntityData[PeopleEditorEntityDataKeys.DisplayName] = claimValue;
                    entity.EntityType = SPClaimEntityTypes.FormsRole;
                    entity.IsResolved = true;
                    resolved.Add(entity);
                }
            }
    
    
            /// <summary>
            /// Required if you implement claim resolution in the People Picker.
            /// </summary>
            /// <param name="context"></param>
            /// <param name="entityTypes"></param>
            /// <param name="resolveInput"></param>
            /// <param name="resolved"></param>
            protected override void FillResolve(Uri context, string[] entityTypes, string resolveInput, List<PickerEntity> resolved)
            {
    
                string keyword = resolveInput.ToLower();
                Hashtable knownClaims = CRMUserInfo.GetAllClaims();
                List<string> knownClaimsList = new List<string>();
    
                // Convert the knownClaims.Key into a List<string> for LINQ query.
                foreach (string claim in knownClaims.Keys)
                {
                    knownClaimsList.Add(claim);
                }
    
                var claimQuery = knownClaimsList.Where(claim => claim.IndexOf(keyword) >= 0).Select(claim => claim);
    
                foreach (string claimValue in claimQuery)
                {
    
                    // Get the ClaimType for the claim type.
                    // For example, if you search "SalesManager", 
                    // the ClaimType will be CRMClaimType.Role.
    
                    string claimType = CRMUserInfo.GetClaimTypeForRole((string)knownClaims[claimValue]);
    
                    PickerEntity entity = CreatePickerEntity();
                    entity.Claim = CreateClaim(claimType, claimValue, Microsoft.IdentityModel.Claims.ClaimValueTypes.String);
                    entity.Description = claimValue;
                    entity.DisplayText = claimValue;
                    entity.EntityData[PeopleEditorEntityDataKeys.DisplayName] = claimValue;
                    entity.EntityType = SPClaimEntityTypes.FormsRole;
                    entity.IsResolved = true;
                    resolved.Add(entity);
                }
    
            }
    
  10. 添加以下 FillHierarchy 方法。此方法是实现抽象类的所有函数所必需的。

    备注

    有关如何实现层次结构的示例,请参阅声明演练:编写 SharePoint 2010 的声明提供程序

            protected override void FillHierarchy(Uri context, string[] entityTypes, string hierarchyNodeID, int numberOfLevels, SPProviderHierarchyTree hierarchy)
            {
                throw new NotImplementedException();
            }
    
  11. 生成项目并更正所有错误。

步骤 4:部署声明提供程序

接下来,部署声明提供程序。

部署声明提供程序

  1. 在解决方案资源管理器中,在"功能"节点下添加一个功能。将此功能重命名为 CRMClaimProvider。

  2. 右键单击"CRMClaimProvider",然后单击"添加事件接收器"。

  3. 将功能的"范围"更改为"服务器场"。

  4. 将命名空间添加到接收器类文件。

    using Microsoft.SharePoint.Administration.Claims;
    
  5. 从 SPClaimProviderFeatureReceiver 派生类。此基接收器提供用于将声明注册到服务器场的函数。

    public class CRMClaimProviderEventReceiver : SPClaimProviderFeatureReceiver
    
  6. 将接收器的实现替换为以下代码。

           private string providerDisplayName = "CRM Claims Provider";
            private string providerDescription = "Provides claims from Contoso CRM system";
    
            public override string ClaimProviderAssembly
            {
                get { return typeof(ContosoClaimProviders.CRMClaimProvider).Assembly.FullName; }
            }
            public override string ClaimProviderType
            {
                get { return typeof(ContosoClaimProviders.CRMClaimProvider).FullName; }
            }
            public override string ClaimProviderDisplayName
            {
                get
                {
                    return providerDisplayName;
                }
            }
            public override string ClaimProviderDescription
            {
                get
                {
                    return providerDescription;
                }
            }
    
  7. 生成项目并将项目部署到服务器场。

步骤 5:从网站中移除用户

接下来,移除用户。

从网站中移除用户

  1. 导航到 http://intranet.contoso.com:200。

  2. 使用凭据 admin1/pass@word1 登录。

  3. 在"网站操作"菜单上,单击"网站设置"。

  4. 在"用户和权限"部分,单击"人员和组"。

  5. 在左侧导航窗格上单击"更多"。

  6. 如果"bob"、"mary"和"jack"存在则移除。

  7. 如果"Employee"、"TeamManager"和"CEO"存在则移除。

  8. 从右上角的下拉列表中,单击"以其他用户身份登录"。

  9. 尝试以 Bob、Mary 或 Jack 身份登录。您应该会收到一条错误消息,如图 1 所示。

    图 1. "拒绝访问"错误消息

    "拒绝访问"错误消息

    备注

    如果您没有收到拒绝访问错误消息,则返回到前面的步骤,并确保您已删除在步骤 2:添加用户查找函数 中添加的所有用户和角色。

步骤 6:测试声明搜索功能

接下来,应测试声明搜索功能。

测试声明搜索功能

  1. 导航到 http://intranet.contoso.com:200。

  2. 使用凭据 admin1/pass@word1 登录。

  3. 在"网站操作"菜单上,单击"网站权限"。

  4. 在功能区上单击"授予权限"。"授予权限"对话框将显示,并且"浏览"图标显示在"用户/组"下,如图 2 所示。

    图 2. 带有"人员选取器"图标的"授予权限"对话框

    "授予权限"对话框

  5. 单击"浏览"图标可启动"人员选取器"对话框,如图 3 所示。

    图 3. "人员选取器"对话框

    人员选取器

  6. 在搜索框中键入 sales,然后单击"搜索"。随即应显示两个结果,如图 4 所示。

    图 4. 搜索与销售相关的声明

    搜索与销售相关的声明

  7. 双击每个结果以将这两个结果添加到"添加"字段。

  8. 单击"确定"关闭"人员选取器"。您应看到 salesmanager 角色和 salesrepresentative 角色已添加到"用户/组"字段,如图 5 所示。

  9. 在"授予权限"下选择"FBA Site Members [Contributor]"。

    图 5. 选择"FBA Site Members (Contributor)"

    选择 FBA 网站成员

  10. 单击"确定"。

  11. 在左侧导航窗格上单击"FBA Site Members"。此时应显示 salesmanager 和 salesrepresentative 角色(声明)已添加到"FBA Site Members"组,如图 6 所示。

    图 6. Salesmanager 和 salesrepresentative 角色位于"FBA Site Members"组中

    销售经理和销售代表角色

  12. 从右上角的下拉列表中,单击"以其他用户身份登录"。

  13. 尝试以 Bob 或 Mary 身份登录。

  14. 接下来,尝试以 Jack 身份登录。您可以登录吗?如果登录失败,原因是什么?

  15. 现在,使用凭据 admin1/pass@word1 登录。

  16. 重复此过程的步骤 3 到步骤 10,以添加 Executive 角色。

  17. 尝试使用 Jack 的凭据登录,查看您现在是否登录成功。

  18. 重复此过程的步骤 3 到步骤 10,以添加区域声明 East 和 Northwest。

  19. 测试 East 和 Northwest 的登录行为。

步骤 6.1:对声明进行解码

接下来,对声明进行解码。

对声明进行解码

  1. 在"网站操作"菜单上,单击"网站设置"。

  2. 在"用户和权限"部分,单击"人员和组"。

  3. 在"人员和组"页上,单击"salesmanager"以显示与 salesmanager 声明相关的信息,如图 7 所示。

    备注

    如果您还未将 salesmanager 角色添加到"人员和组"页,则立即进行添加。有关如何将 salesmanager 角色添加到"人员和组"页的信息,请参阅步骤 6:测试声明搜索功能。

    图 7. Salesmanager 声明

    销售经理声明

  4. 查看"帐户"名称,并使用附录 A:标识声明编码字符映射 中的编码表来解密每个字符。

步骤 7:测试声明解析功能

接下来,测试声明解析功能。

测试声明解析功能

  1. 重复步骤 5:从网站中移除用户 以移除添加到网站的所有用户声明。

  2. 导航到 http://intranet.contoso.com:200。

  3. 使用凭据 admin1/pass@word1 登录。

  4. 在"网站操作"菜单上,单击"网站权限"。

  5. 在功能区上单击"授予权限"。"授予权限"对话框将显示,并且"浏览"图标显示在"用户/组"下,如图 8 所示。

    图 8. 带有"人员选取器"图标的"授予权限"对话框

    "授予权限"对话框

  6. 在"用户/组"文本框中键入 salesmanager。单击位于"用户/组"文本框右下角的"检查名称"图标以解析名称,如图 9 所示。

    图 9. 解析 salesmanager 声明

    解析销售经理声明

  7. 单击"确定"以将 salesmanager 声明添加到"FBA Site Members"组中。

  8. 重复此过程前面的步骤,以测试 Bob、Mary 和 Jack 的登录行为。

  9. 在"用户/组"文本框中键入 sales 以尝试通配符搜索。应返回多个实体,如图 10 所示。

    备注

    您不能像在"浏览"对话框中一样指定声明提供程序。您可以选择单击"更多名称"来显示"浏览"对话框。

    图 10. 通配符搜索

    通配符搜索

步骤 8:调试声明提供程序

接下来,利用您在前面测试步骤中学到的内容,调试声明扩充、搜索和解析过程:

  • 如果要调试声明扩充过程,则对于 SharePoint 安全令牌服务 (STS),您需要附加到 w3wp.exe。

  • 如果要为 Web 应用程序调试声明搜索或声明解析,则附加到 w3wp.exe。

  • 如果您已更改声明提供程序,则必须执行 iisreset,因为 Microsoft Visual Studio 2010 不会回收 SharePoint STS 过程;而 STS 过程可能仍引用旧版的声明提供程序。

步骤 9:添加对 Windows 帐户的支持

接下来,启用对 http://intranet.contoso.com:200 的 Windows 身份验证和基于表单的身份验证支持。

添加对 Windows 帐户的支持

  1. 启动"管理中心"网站。

  2. 在左侧导航窗格中单击"安全"。

  3. 在"一般安全性"部分单击"指定身份验证提供程序"。

  4. 在"Web 应用程序"下拉列表中选择"http://intranet.contoso.com:200"。

  5. 在"区域"下单击"默认",如图 11 所示。

    图 11. "身份验证提供程序"页

    身份验证提供程序页

  6. 选中"启用 Windows 身份验证"复选框,然后选择"集成 Windows 身份验证",如图 12 所示。

    图 12. 选择声明身份验证类型

    选择声明身份验证类型

  7. 单击"保存"。

  8. 运行 iisreset。

  9. 返回到声明提供程序源代码,并确保已将您的域帐户添加到 userDB 数组。

    备注

    在此示例中,我们已为 contoso\administrator 添加 SalesManager 角色。

            private static string[] userDB = 
               {
                "bob:CRMRole:Reader", 
                "bob:CRMRole:SalesRepresentative",
                "bob:CRMRegion:Northwest",
                "mary:CRMRole:Reader",
                "mary:CRMRole:SalesManager",
                "mary:CRMRegion:East",
                "jack:CRMRole:Reader",
                "jack:CRMRole:Executive",
                "jack:CRMRegion:East",
                "admin1:CRMRole:Administrator",
                "contoso\\andy:CRMRole:SalesManager",
                 contoso\\administrator:CRMRole:SalesManager
               };
    
  10. 导航到 http://intranet.contoso.com:200。

  11. 使用凭据 admin1/pass@word1 登录。

  12. 在"网站操作"菜单上,单击"网站权限"。

  13. 将网站权限授予 SalesManager 角色(如果您尚未这样做)。

  14. 在右上角的下拉列表中,单击"以其他用户身份登录"。

  15. "多身份验证选择器"页将显示,如图 13 所示。

    图 13. "多身份验证选择器"页

    多个身份验证选择器页

  16. 在下拉列表上选择"Windows 身份验证"。您应该会自动登录到网站。

    备注

    当选择"Windows 身份验证"时,您会被重定向到 /_windows/default.aspx,执行无人参与 NTLM 身份验证。然后您将重定向回网站。

  17. 查看声明查看器 Web 部件,检查已为 contoso\administrator 添加了哪些声明。

步骤 10:更改声明范围

您将自行执行此步骤。此任务是在 http://intranet.contoso.com/sites/CRMDocs 下创建网站集。然后向网站中添加以下内容:

  • 文档库:CustomerDocs

  • 自定义列表:East_Customers

我们希望此声明提供程序是唯一适用于此网站的声明提供程序。

目标是:

  • 如果用户登录 http://intranet.contoso.com,则在用户的声明令牌中应没有 CRM 声明。声明查看器 Web 部件不会显示任何与 CRM 相关的声明。

  • 只有 CRMRole=Reader 的用户才能登录 http://intranet.contoso.com/sites/CRMDocs 网站。

  • CRMRole=Executive 的用户可以访问 CustomerDocs 库。

  • CRMRegion=East 的用户可以访问 East_Customers 列表。

利用您所学到的内容完成此任务。为了帮助您理解和记忆,您可能需要写下代码。

结论

在此演练中,了解如何为使用基于表单的身份验证的 SharePoint 2010 Web 应用程序创建声明提供程序,并测试所创建的声明提供程序。

附录 A:标识声明编码字符映射

表 1. 声明类型编码

字符

声明类型

!

SPClaimTypes.IdentityProvider

"

SPClaimTypes.UserIdentifier

#

SPClaimTypes.UserLogonName

$

SPClaimTypes.DistributionListClaimType

%

SPClaimTypes.FarmId

&

SPClaimTypes.ProcessIdentitySID

SPClaimTypes.ProcessIdentityLogonName

(

SPClaimTypes.IsAuthenticated

)

Microsoft.IdentityModel.Claims.ClaimTypes.PrimarySid

*

Microsoft.IdentityModel.Claims.ClaimTypes.PrimaryGroupSid

+

Microsoft.IdentityModel.Claims.ClaimTypes.GroupSid

-

Microsoft.IdentityModel.Claims.ClaimTypes.Role

.

System.IdentityModel.Claims.ClaimTypes.Anonymous

/

System.IdentityModel.Claims.ClaimTypes.Authentication

0

System.IdentityModel.Claims.ClaimTypes.AuthorizationDecision

1

System.IdentityModel.Claims.ClaimTypes.Country

2

System.IdentityModel.Claims.ClaimTypes.DateOfBirth

3

System.IdentityModel.Claims.ClaimTypes.DenyOnlySid

4

System.IdentityModel.Claims.ClaimTypes.Dns

5

System.IdentityModel.Claims.ClaimTypes.Email

6

System.IdentityModel.Claims.ClaimTypes.Gender

7

System.IdentityModel.Claims.ClaimTypes.GivenName

8

System.IdentityModel.Claims.ClaimTypes.Hash

9

System.IdentityModel.Claims.ClaimTypes.HomePhone

<

System.IdentityModel.Claims.ClaimTypes.Locality

=

System.IdentityModel.Claims.ClaimTypes.MobilePhone

>

System.IdentityModel.Claims.ClaimTypes.Name

?

System.IdentityModel.Claims.ClaimTypes.NameIdentifier

@

System.IdentityModel.Claims.ClaimTypes.OtherPhone

[

System.IdentityModel.Claims.ClaimTypes.PostalCode

\

System.IdentityModel.Claims.ClaimTypes.PPID

]

System.IdentityModel.Claims.ClaimTypes.Rsa

^

System.IdentityModel.Claims.ClaimTypes.Sid

_

System.IdentityModel.Claims.ClaimTypes.Spn

`

System.IdentityModel.Claims.ClaimTypes.StateOrProvince

a

System.IdentityModel.Claims.ClaimTypes.StreetAddress

b

System.IdentityModel.Claims.ClaimTypes.Surname

c

System.IdentityModel.Claims.ClaimTypes.System

d

System.IdentityModel.Claims.ClaimTypes.Thumbprint

e

System.IdentityModel.Claims.ClaimTypes.Upn

f

System.IdentityModel.Claims.ClaimTypes.Uri

g

System.IdentityModel.Claims.ClaimTypes.Webpage

表 2. 声明值类型编码

字符

声明类型

!

Microsoft.IdentityModel.Claims.ClaimValueTypes.Base64Binary

"

Microsoft.IdentityModel.Claims.ClaimValueTypes.Boolean

#

Microsoft.IdentityModel.Claims.ClaimValueTypes.Date

$

Microsoft.IdentityModel.Claims.ClaimValueTypes.Datetime

%

Microsoft.IdentityModel.Claims.ClaimValueTypes.DaytimeDuration

&

Microsoft.IdentityModel.Claims.ClaimValueTypes.Double

Microsoft.IdentityModel.Claims.ClaimValueTypes.DsaKeyValue

(

Microsoft.IdentityModel.Claims.ClaimValueTypes.HexBinary

)

Microsoft.IdentityModel.Claims.ClaimValueTypes.Integer

*

Microsoft.IdentityModel.Claims.ClaimValueTypes.KeyInfo

+

Microsoft.IdentityModel.Claims.ClaimValueTypes.Rfc822Name

-

Microsoft.IdentityModel.Claims.ClaimValueTypes.RsaKeyValue

.

Microsoft.IdentityModel.Claims.ClaimValueTypes.String

/

Microsoft.IdentityModel.Claims.ClaimValueTypes.Time

0

Microsoft.IdentityModel.Claims.ClaimValueTypes.X500Name

1

Microsoft.IdentityModel.Claims.ClaimValueTypes.YearMonthDuration

其他资源

有关详细信息,请参阅以下资源: