如何:从 .NET 连接程序集中使用 Secure Store Service

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

适用范围: SharePoint Server 2010

本文内容
在 .NET 连接程序集中使用安全存储时采用的无代码方法
在 .NET 连接程序集中使用安全存储时采用的代码方法
摘要

数据库、Web 服务和 Windows Communication Foundation (WCF) 服务连接器都只使用一个外部系统。Microsoft Business Connectivity Services (BCS) 可连接到这些外部系统和本机支持这些连接器的安全存储集成。但对于 Microsoft .NET Framework 程序集连接器,.NET 程序集代码可使用零个、一个或多个外部系统。由于 Business Connectivity Services 无法确定 .NET 程序集代码执行的操作,因此它不本机支持针对 .NET 程序集连接器的安全存储集成。但是,Business Connectivity Services 提供了两类不同的机制以便在 .NET 连接程序集中使用安全存储。

在第一类机制(无代码方法)中,Business Connectivity Services 将执行从安全存储读取凭据所需的操作。在第二类机制(代码方法)中,.NET 连接程序集将执行必要的操作。本主题描述了这两类机制。

在 .NET 连接程序集中使用安全存储时采用的无代码方法

顾名思义,.NET 连接程序集不会与 安全存储 直接交互。利用筛选器,它可以使用 Business Connectivity Services 从 安全存储 读取凭据并将凭据获取为方法的输入参数。此方法并非专用于 .NET 程序集连接器,它可用于数据库连接器、Web 服务连接器和 WCF 连接器。

在 .NET 连接程序集中编写方法时,您必须具有凭据的输入参数。以下示例演示带 username 和 password 输入参数以及其他参数的 GetEntity 方法。

public SampleEntity GetEntity(string username, string password, int id)
{ 
    // Parameters username and password 
    // contain the credentials.
}

若要获取 username 和 password 参数中的凭据,您必须使用 UsernameFilter 和 PasswordFilter 筛选器。在元数据模型中,您必须定义 LobSystemInstance 的 SecondarySsoApplicationId 和 SsoProviderImplementation 属性,并将筛选器关联到方法的相应输入参数。当 Business Connectivity Services 遇到筛选器时,它将为安全存储目标应用程序 ID 和安全存储提供程序分别使用 SecondarySsoApplicationId 属性和 SsoProviderImplementation 属性。

<LobSystemInstance ...> 
  <Properties> 
    <!-- Other properties omitted. –> 
    <Property Name="SecondarySsoApplicationId" 
        Type="System.String">MyLobAppId</Property> 
    <Property Name="SsoProviderImplementation" Type="System.String"> 
        Microsoft.Office.SecureStoreService.Server.SecureStoreProvider, Microsoft.Office.SecureStoreService, 
        Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Property> 
  </Properties> 
</LobSystemInstance> 

下面我们为方法定义两个筛选器。

<Method Name="GetEntity"> 
  <FilterDescriptors> 
    <FilterDescriptor Type="Username" Name="UserNameFilter"/> 
    <FilterDescriptor Type="Password" Name="PasswordFilter"/> 
  </FilterDescriptors> 
</Method>

现已为方法定义筛选器,以下示例将演示如何将这两个筛选器关联到方法的输入参数。

<Parameter Direction="In" Name="username">  
    <TypeDescriptor TypeName="System.String" Name="username" 
        AssociatedFilter="UserNameFilter"/> 
</Parameter> 
<Parameter Direction="In" Name="password">  
    <TypeDescriptor TypeName="System.String" Name="password" 
        AssociatedFilter="PasswordFilter"/> 
</Parameter>

这是在 .NET 连接程序集中使用安全存储时所需的方法。当 Business Connectivity Services 执行此方法时,它会从安全存储读取凭据并在方法的输入参数中设置凭据。

在 .NET 连接程序集中使用安全存储时采用的代码方法

在编写代码以使用安全存储之前,您应了解 Business Connectivity Services 如何在其他连接器中使用安全存储。在 Business Connectivity Services 中,其他连接器依赖于元数据模型来获取有关安全存储和目标应用程序 ID 的信息。连接器使用此信息来检索凭据,以便对外部系统进行身份验证。例如,对于数据库连接器,将显示元数据模型中的 LobSystemInstance 的属性,如以下示例所示。

<LobSystemInstance ...> 
  <Properties> 
    <!-- Other properties omitted. –> 
    <Property Name="SsoApplicationId" 
        Type="System.String">MyLobAppId</Property> 
    <Property Name="SsoProviderImplementation" Type="System.String"> Microsoft.Office.SecureStoreService.Server.SecureStoreProvider, Microsoft.Office.SecureStoreService, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Property> 
  </Properties> 
</LobSystemInstance>

数据库连接器将读取元数据模型,并确定需要凭据以连接到数据库并可从指定的安全存储提供程序获取这些凭据。在数据库连接器具有安全存储提供程序的必要信息后,它将从提供程序读取凭据并模拟用户以进行数据库连接。

以下各节说明如何读取 .NET 程序集代码中的元数据模型属性以及如何使用安全存储 API 来读取用户凭据。

读取 .NET 连接程序集中的元数据模型属性

若要读取 .NET 连接程序集中的元数据模型属性,则 .NET 程序集中的代码必须实现 IContextProperty 接口。以下代码演示 IContextProperty 接口的示例实现。

IContextProperty 的示例实现

using IContextProperty = Microsoft.BusinessData.SystemSpecific.IContextProperty; 
public class SampleConnector : IContextProperty 
{ 
    private IMethodInstance methodInstance; 
    private ILobSystemInstance lobSystemInstance; 
    private IExecutionContext executionContext;
    #region IContextProperty implementation 
    public IMethodInstance MethodInstance 
    { 
        get { return this.methodInstance; } 
        set { this.methodInstance = value; } 
    }
    public ILobSystemInstance LobSystemInstance 
    { 
        get { return this.lobSystemInstance; } 
        set { this.lobSystemInstance = value; } 
    } 
    public IExecutionContext ExecutionContext 
    { 
        get { return this.executionContext; } 
        set { this.executionContext = value; } 
    } 
        #endregion 
        // Unrelated code removed for brevity. 
} 

当 .NET 连接程序集类实现 IContextProperty 接口时,Business Connectivity Services 运行时将自动初始化 IContextProperty 属性。

在运行时,代码具有它在其中执行的上下文(方法实例和 LobSystem Instance);在代码中实现的方法可从元数据模型中读取属性。以下代码演示如何读取 LobSystemInstance 属性。

public SampleEntity GetEntity(int id) 
{ 
    // Read the LobSystemInstance property defined in the metadata model. 
    string provider =  
        LobSystemInstance.GetProperties()["ssoProviderImplementation"] 
        as string; 
    // Unrelated code removed for brevity. 
} 

与 Secure Store Service 进行交互

当 .NET 连接程序集需要从安全存储读取凭据时,请使用以下属性名称。

  • ssoProviderImplementation   安全存储提供程序

  • SecondarySsoApplicationId   安全存储的目标应用程序

在 Microsoft SharePoint Designer 2010 中对构建 .NET 程序集连接器模型时支持 ssoProviderImplementation 和 SecondarySsoApplicationId 属性。如果 .NET 连接程序集需要从安全存储读取多个凭据,则选择对您的方案最有用的属性名。

用于从安全存储读取凭据的示例实现

第一个步骤是通过提供程序实现来实例化安全存储提供程序。在代码中,确保提供程序实现 ISecureStoreProvider 接口。以下示例演示用于实例化安全存储提供程序的简单实现。

private ISecureStoreProvider GetSecureStoreProvider() 
{
    // Error checking removed for brevity.
string provider = this.LobSystemInstance.GetProperties()  
    ["ssoProviderImplementation"] as string; 
Type providerType = Type.GetType(provider); 
return Activator.CreateInstance(providerType)  
    as ISecureStoreProvider;
} 

在实例化安全存储提供程序后,从安全存储获取凭据。安全存储将为用户返回一个 SecureStoreCredentialCollection(它包含凭据集合)和一个目标 ID。ISecureStoreCredential 接口定义了凭据类型和值。

以下示例演示如何从安全存储读取凭据。这些凭据可用于对外部系统进行身份验证。

private void ReadCredentialsFromSecureStore() 
{ 
    // Error checking removed for brevity. 
    string targetId = 
        LobSystemInstance.GetProperties()["SecondarySsoApplicationId"]  
        as string; 
    ISecureStoreProvider provider = GetSecureStoreProvider();
    // Get the credentials for the user on whose behalf the code 
    // is executing. 
    using(SecureStoreCredentialCollection credentials =      
        provider.GetRestrictedCredentials(targetId)) 
    { 
        SecureString secureUsername; 
        SecureString securePassword; 
         // Look for username and password in credentials. 
        foreach (ISecureStoreCredential credential in credentials) 
        { 
            switch (credential.CredentialType) 
            { 
                case SecureStoreCredentialType.UserName: 
                case SecureStoreCredentialType.WindowsUserName: 
                    secureUsername = credential.Credential; 
                    break; 
                case SecureStoreCredentialType.Password: 
                case SecureStoreCredentialType.WindowsPassword: 
                    securePassword = credential.Credential; 
                    break; 
                default: 
                    break; 
            } 
        } 
        // Username and password have been read. 
        // Use them as necessary.  
    } 
     // NOTE:  Because we are getting the credentials in the using block,  
    // all the credentials that we get will be disposed after the 
    // using block. If you need to cache the credentials,  do not use 
    // a using block but dispose the credentials when you are done 
     // with them.
} 

摘要

可以选择无代码方法或代码方法来使用 .NET 连接程序集中的安全存储,具体取决于方案。表 1 概括了这两种方法之间的差异。

表 1. 无代码方法与代码方法之间的差异摘要

领域

无代码方法

代码方法

与所需的安全存储 API 进行交互

专用于 .NET 程序集连接器

SharePoint Designer 支持

部分

影响方法签名

从多个安全存储读取

是否可在 LobSystemInstance 级别设置凭据