SecurityTokenService 类

定义

定义安全令牌服务 (STS) 的属性和方法的抽象基类。

public ref class SecurityTokenService abstract
public abstract class SecurityTokenService
type SecurityTokenService = class
Public MustInherit Class SecurityTokenService
继承
SecurityTokenService

示例

主题中使用的 SecurityTokenService 代码示例取自示例 Custom Token 。 此示例提供自定义类,这些类支持处理简单 Web 令牌 (SWT) ,并包含能够为 SWT 令牌提供服务的被动 STS 的实现。 有关如何实现活动 STS 的示例,请参阅示例 Federation Metadata 。 有关这些示例和可用于 WIF 的其他示例以及下载位置的信息,请参阅 WIF 代码示例索引。 以下代码演示如何使用 SecurityTokenService 类实现被动 STS。

using System;
using System.IdentityModel;
using System.IdentityModel.Configuration;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Tokens;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;

namespace PassiveSTS
{
    /// <summary>
    /// Overrides the SecurityTokenService class to provide
    /// the relying party related information, such as encryption credentials to encrypt the issued
    /// token, signing credentials to sign the issued token, claims that the STS wants to issue for a 
    /// certain token request, as well as the claim types that this STS is capable
    /// of issuing.
    /// </summary>
    public class CustomSecurityTokenService : SecurityTokenService
    {
        // Certificate Constants
        private const string SIGNING_CERTIFICATE_NAME = "CN=localhost";
        private const string ENCRYPTING_CERTIFICATE_NAME = "CN=localhost";

        private SigningCredentials _signingCreds;
        private EncryptingCredentials _encryptingCreds;
        // Used for validating applies to address, set to URI used in RP app of application, could also have been done via config
        private string _addressExpected = "http://localhost:19851/";
        public CustomSecurityTokenService(SecurityTokenServiceConfiguration configuration)
            : base(configuration)
        {
            // Setup the certificate our STS is going to use to sign the issued tokens
            _signingCreds = new X509SigningCredentials(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, SIGNING_CERTIFICATE_NAME));

            // Note: In this sample app only a si   ngle RP identity is shown, which is localhost, and the certificate of that RP is 
            // populated as _encryptingCreds
            // If you have multiple RPs for the STS you would select the certificate that is specific to 
            // the RP that requests the token and then use that for _encryptingCreds
            _encryptingCreds = new X509EncryptingCredentials(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, ENCRYPTING_CERTIFICATE_NAME));
        }

        /// <summary>
        /// This method returns the configuration for the token issuance request. The configuration
        /// is represented by the Scope class. In our case, we are only capable of issuing a token to a
        /// single RP identity represented by the _encryptingCreds field.
        /// </summary>
        /// <param name="principal">The caller's principal</param>
        /// <param name="request">The incoming RST</param>
        /// <returns></returns>
        protected override Scope GetScope(ClaimsPrincipal principal, RequestSecurityToken request)
        {
            // Validate the AppliesTo address
            ValidateAppliesTo( request.AppliesTo );

            // Create the scope using the request AppliesTo address and the RP identity
            Scope scope = new Scope( request.AppliesTo.Uri.AbsoluteUri, _signingCreds );

            if (Uri.IsWellFormedUriString(request.ReplyTo, UriKind.Absolute))
            {
                if (request.AppliesTo.Uri.Host != new Uri(request.ReplyTo).Host)
                    scope.ReplyToAddress = request.AppliesTo.Uri.AbsoluteUri;
                else
                    scope.ReplyToAddress = request.ReplyTo;
            }
            else
            {
                Uri resultUri = null;
                if (Uri.TryCreate(request.AppliesTo.Uri, request.ReplyTo, out resultUri))
                    scope.ReplyToAddress = resultUri.AbsoluteUri;
                else
                    scope.ReplyToAddress = request.AppliesTo.Uri.ToString() ;
            }

            // Note: In this sample app only a single RP identity is shown, which is localhost, and the certificate of that RP is 
            // populated as _encryptingCreds
            // If you have multiple RPs for the STS you would select the certificate that is specific to 
            // the RP that requests the token and then use that for _encryptingCreds
            scope.EncryptingCredentials = _encryptingCreds;

            return scope;
        }
        /// <summary>
        /// This method returns the content of the issued token. The content is represented as a set of
        /// IClaimIdentity intances, each instance corresponds to a single issued token. Currently, the Windows Identity Foundation only
        /// supports a single token issuance, so the returned collection must always contain only a single instance.
        /// </summary>
        /// <param name="scope">The scope that was previously returned by GetScope method</param>
        /// <param name="principal">The caller's principal</param>
        /// <param name="request">The incoming RST, we don't use this in our implementation</param>
        /// <returns></returns>
        protected override ClaimsIdentity GetOutputClaimsIdentity( ClaimsPrincipal principal, RequestSecurityToken request, Scope scope )
        {
            //
            // Return a default claim set which contains a custom decision claim
            // Here you can actually examine the user by looking at the IClaimsPrincipal and 
            // return the right decision based on that. 
            //
            ClaimsIdentity outgoingIdentity = new ClaimsIdentity();
            outgoingIdentity.AddClaims(principal.Claims);

            return outgoingIdentity;
        }
        /// <summary>
        /// Validates the appliesTo and throws an exception if the appliesTo is null or appliesTo contains some unexpected address.
        /// </summary>
        /// <param name="appliesTo">The AppliesTo parameter in the request that came in (RST)</param>
        /// <returns></returns>
        void ValidateAppliesTo(EndpointReference appliesTo)
        {
            if (appliesTo == null)
            {
                throw new InvalidRequestException("The appliesTo is null.");
            }

            if (!appliesTo.Uri.Equals(new Uri(_addressExpected)))
            {
                throw new InvalidRequestException(String.Format("The relying party address is not valid. Expected value is {0}, the actual value is {1}.", _addressExpected, appliesTo.Uri.AbsoluteUri));
            }
        }

    }
}

以下代码演示如何调用自定义被动 STS,以通过从 文件中的代码隐藏default.aspx.cs调用 FederatedPassiveSecurityTokenServiceOperations.ProcessRequest(HttpRequest, ClaimsPrincipal, SecurityTokenService, HttpResponse) 方法来处理 WS-Federation 请求。

using System;
using System.IdentityModel.Services;
using System.Security.Claims;

namespace PassiveSTS
{
    public partial class _Default : System.Web.UI.Page
    {
        /// <summary>
        /// We perform the WS-Federation Passive Protocol processing in this method. 
        /// </summary>
        protected void Page_PreRender( object sender, EventArgs e ) 
        {
            FederatedPassiveSecurityTokenServiceOperations.ProcessRequest( Request, User as ClaimsPrincipal, CustomSecurityTokenServiceConfiguration.Current.CreateSecurityTokenService(), Response );
        }
    }
}

注解

若要创建 STS,必须从 SecurityTokenService 类派生。 在自定义类中,至少必须重写 GetScopeGetOutputClaimsIdentity 方法。 通过这些替代,使用 类中定义的所有其他方法的默认实现创建的 STS 能够颁发安全令牌,以响应安全令牌请求 (RST) 。 也就是说,实现 WS-Trust 规范中定义的 Issue 绑定。 此绑定在 方法中 Issue 实现。 默认情况下,不会实现其他 WS-Trust 绑定 (Renew、Cancel 和 Validate) ,如果遇到与其中一个绑定对应的 RST,则会向调用方返回相应的错误。 当然,可以替代 (RenewCancelValidate) 的适当方法,以在 STS 中实现这些绑定。

重要

实现生产就绪 STS 需要仔细规划和大量资源,以缓解暴露此类服务固有的潜在安全风险。 大多数使用 Windows Identity Foundation (WIF) 的开发人员将开发将标识管理外包给 STS 的应用程序,而不是开发 STS 本身。 WIF 提供 Visual Studio 扩展,即 Visual Studio 2012 的标识和访问工具,以帮助开发人员在开发环境中测试解决方案。 此工具包括 STS , LocalSTS可以对其进行配置,以便为正在开发的应用程序提供特定的声明。 有关标识和访问工具的详细信息,请参阅 Visual Studio 2012 的标识和访问工具。 在某些情况下, LocalSTS 可能不会提供充分测试应用程序所需的功能;例如,在涉及开发供应用程序使用的自定义令牌处理程序的方案中。 在这些情况下,可以从 派生 SecurityTokenService ,以创建一个或多个可在开发环境中部署并可用于在应用程序中测试此类功能的简单 STS。 本部分的其余部分重点介绍 类公开 SecurityTokenService 的方法,这些方法使你能够实现简单的 STS 并扩展令牌颁发管道。

以下列表简要概述了开发人员在测试或开发环境中使用的重要方法。

  • GetScope 方法。 此方法返回一个 Scope 对象,该对象包含有关 RP 的信息。 此对象在令牌颁发管道的其余部分使用,包括有关在响应中使用的签名和加密凭据的信息,以及 AppliesToReplyTo 如果需要) 地址, (。 必须重写此方法。

  • GetOutputClaimsIdentity 方法。 此方法返回一个 ClaimsIdentity 对象,该对象包含要返回到 RP 的声明。 必须重写此方法。

  • Issue 方法。 此方法实现令牌请求管道,该管道 (RST) 处理传入的安全令牌请求,并将响应 (RSTR) 返回给调用方,该调用方包含可用于向 RP 进行身份验证的令牌。 类中 SecurityTokenService 定义的许多其他方法都是从此方法调用的 GetScope ,包括 和 GetOutputClaimsIdentity 方法。 无需重写此方法,但了解它实现的令牌请求管道可能会有所帮助。

STS 是通过 SecurityTokenServiceConfiguration 类配置的。

实施者说明

必须同时重写 GetScope(ClaimsPrincipal, RequestSecurityToken)GetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope) 方法。

构造函数

SecurityTokenService(SecurityTokenServiceConfiguration)

已从派生的类中调用,以使用指定的配置设置初始化 SecurityTokenService 类。

属性

Principal

获取或设置与当前实例关联的主体。

Request

获取或设置要与当前实例关联的安全性标记请求 (RST) 。

Scope

获取或设置与当前实例关联的范围。

SecurityTokenDescriptor

获取或设置与当前 SecurityTokenDescriptor 实例关联的数据。

SecurityTokenServiceConfiguration

获取实例所有者的配置。

方法

BeginCancel(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

在派生类中重写时,开始异步 WS 信任取消请求。

BeginGetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope, AsyncCallback, Object)

当在派生类中重写时,开始对 GetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope) 方法的异步调用。

BeginGetScope(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

当在派生类中重写时,开始对 GetScope(ClaimsPrincipal, RequestSecurityToken) 方法的异步调用。

BeginIssue(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

在派生类中重写时,开始异步 WS 信任发布请求。

BeginRenew(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

在派生类中重写时,开始异步 WS 信任更新请求。

BeginValidate(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

在派生类中重写时,开始异步 WS 信任验证请求。

Cancel(ClaimsPrincipal, RequestSecurityToken)

在派生类中重写时,处理 WS 信任取消请求。

CreateSecurityTokenDescriptor(RequestSecurityToken, Scope)

创建 SecurityTokenDescriptor 的实例。

EndCancel(IAsyncResult)

在派生类中重写时,完成异步 WS 信任取消请求。

EndGetOutputClaimsIdentity(IAsyncResult)

当在派生类中重写时,完成对 BeginGetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope, AsyncCallback, Object) 方法的异步调用。

EndGetScope(IAsyncResult)

当在派生类中重写时,完成对 BeginGetScope(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object) 方法的异步调用。

EndIssue(IAsyncResult)

在派生类中重写时,完成异步 WS 信任发布请求。

EndRenew(IAsyncResult)

在派生类中重写时,完成异步 WS 信任更新请求。

EndValidate(IAsyncResult)

在派生类中重写时,完成异步 WS 信任验证请求。

Equals(Object)

确定指定对象是否等于当前对象。

(继承自 Object)
GetHashCode()

作为默认哈希函数。

(继承自 Object)
GetIssuerName()

获取或设置安全标记服务的 (STS) 的名称。

GetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope)

当在派生类中重写时,此方法将返回要包括在颁发令牌中的输出主题的集合。

GetProofToken(RequestSecurityToken, Scope)

获取要包含在响应(RETR) 内的证明标记。

GetRequestorProofEncryptingCredentials(RequestSecurityToken)

获取请求者的标记加密凭据。

GetResponse(RequestSecurityToken, SecurityTokenDescriptor)

创建响应 (RSTR),它包含使用指定请求 (RST) 和安全令牌描述符颁发的令牌。

GetScope(ClaimsPrincipal, RequestSecurityToken)

获取包含与指定请求(RST)关联的依赖方(RP)信息的 Scope 对象。 实现该 SecurityTokenService 类时,必须重写此方法。

GetSecurityTokenHandler(String)

获取适合保护指定类型的安全令牌的安全令牌处理程序。

GetTokenLifetime(Lifetime)

获取颁发的令牌的生存期。

GetType()

获取当前实例的 Type

(继承自 Object)
Issue(ClaimsPrincipal, RequestSecurityToken)

发出安全令牌。

MemberwiseClone()

创建当前 Object 的浅表副本。

(继承自 Object)
Renew(ClaimsPrincipal, RequestSecurityToken)

在派生类中重写时,处理 WS 信任续订请求。

ToString()

返回表示当前对象的字符串。

(继承自 Object)
Validate(ClaimsPrincipal, RequestSecurityToken)

在派生类中重写时,处理 WS 信任验证请求。

ValidateRequest(RequestSecurityToken)

确认该事例 (RST) 封装的安全标记的请求。

适用于

另请参阅