SecurityTokenHandler.ValidateToken(SecurityToken) Método

Definição

Quando substituído em uma classe derivada, valida o token de segurança especificado.When overridden in a derived class, validates the specified security token. O token deve ser do tipo processado pela classe derivada.The token must be of the type processed by the derived class.

public:
 virtual System::Collections::ObjectModel::ReadOnlyCollection<System::Security::Claims::ClaimsIdentity ^> ^ ValidateToken(System::IdentityModel::Tokens::SecurityToken ^ token);
public virtual System.Collections.ObjectModel.ReadOnlyCollection<System.Security.Claims.ClaimsIdentity> ValidateToken (System.IdentityModel.Tokens.SecurityToken token);
abstract member ValidateToken : System.IdentityModel.Tokens.SecurityToken -> System.Collections.ObjectModel.ReadOnlyCollection<System.Security.Claims.ClaimsIdentity>
override this.ValidateToken : System.IdentityModel.Tokens.SecurityToken -> System.Collections.ObjectModel.ReadOnlyCollection<System.Security.Claims.ClaimsIdentity>
Public Overridable Function ValidateToken (token As SecurityToken) As ReadOnlyCollection(Of ClaimsIdentity)

Parâmetros

token
SecurityToken

O token a ser validado.The token to validate.

Retornos

ReadOnlyCollection<ClaimsIdentity>

As identidades contidas no token.The identities contained in the token.

Exemplos

O código a seguir mostra uma substituição do ValidateToken método para um manipulador de token de segurança que processa SWT (tokens da Web simples).The following code shows an override of the ValidateToken method for a security token handler that processes simple web tokens (SWT). O código é extraído do CustomToken exemplo.The code is taken from the CustomToken sample. Para obter informações sobre esse exemplo e outros exemplos disponíveis para o WIF e onde baixá-los, consulte o índice de exemplo de código do WIF.For information about this sample and other samples available for WIF and where to download them, see WIF Code Sample Index.

/// <summary>
/// This method validates the Simple Web Token.
/// </summary>
/// <param name="token">A simple web token.</param>
/// <returns>A Claims Collection which contains all the claims from the token.</returns>
public override ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token)
{
    if ( token == null )
    {
        throw new ArgumentNullException( "token" );
    }

    SimpleWebToken simpleWebToken = token as SimpleWebToken;
    if ( simpleWebToken == null )
    {
        throw new ArgumentException("The token provided must be of type SimpleWebToken.");                    
    }

    if ( DateTime.Compare( simpleWebToken.ValidTo.Add( Configuration.MaxClockSkew ), DateTime.UtcNow ) <= 0 )
    {
        throw new SecurityTokenExpiredException("The incoming token has expired. Get a new access token from the Authorization Server.");
    }

    ValidateSignature( simpleWebToken );
 
    ValidateAudience( simpleWebToken.Audience );
 
    ClaimsIdentity claimsIdentity = CreateClaims( simpleWebToken );
   
    if (this.Configuration.SaveBootstrapContext)
    {
        claimsIdentity.BootstrapContext = new BootstrapContext(simpleWebToken.SerializedToken);
    }

    List<ClaimsIdentity> claimCollection = new List<ClaimsIdentity>(new ClaimsIdentity[] { claimsIdentity });
    return claimCollection.AsReadOnly();
}

O código a seguir mostra o CreateClaims método que é invocado a partir da substituição do ValidateToken método no exemplo anterior.The following code shows CreateClaims method that is invoked from the override of the ValidateToken method in the previous example. Esse método retorna um ClaimsIdentity objeto que é criado a partir das declarações no token.This method returns a ClaimsIdentity object that is created from the claims in the token. O código é extraído do CustomToken exemplo.The code is taken from the CustomToken sample. Para obter informações sobre esse exemplo e outros exemplos disponíveis para o WIF e onde baixá-los, consulte o índice de exemplo de código do WIF.For information about this sample and other samples available for WIF and where to download them, see WIF Code Sample Index.

/// <summary>Creates <see cref="Claim"/>'s from the incoming token.
/// </summary>
/// <param name="simpleWebToken">The incoming <see cref="SimpleWebToken"/>.</param>
/// <returns>A <see cref="ClaimsIdentity"/> created from the token.</returns>
protected virtual ClaimsIdentity CreateClaims( SimpleWebToken simpleWebToken )
{
    if ( simpleWebToken == null )
    {
        throw new ArgumentNullException( "simpleWebToken" );
    }

    NameValueCollection tokenProperties = simpleWebToken.GetAllProperties();
    if ( tokenProperties == null )
    {
        throw new SecurityTokenValidationException( "No claims can be created from this Simple Web Token." );
    }

    if ( Configuration.IssuerNameRegistry == null )
    {
        throw new InvalidOperationException( "The Configuration.IssuerNameRegistry property of this SecurityTokenHandler is set to null. Tokens cannot be validated in this state." );
    }

    string normalizedIssuer = Configuration.IssuerNameRegistry.GetIssuerName( simpleWebToken );

    ClaimsIdentity identity = new ClaimsIdentity(AuthenticationTypes.Federation);
    
    foreach ( string key in tokenProperties.Keys )
    {
        if ( ! IsReservedKeyName(key) &&  !string.IsNullOrEmpty( tokenProperties[key] ) )
        {
            identity.AddClaim( new Claim( key, tokenProperties[key], ClaimValueTypes.String, normalizedIssuer ) );
            if ( key == AcsNameClaimType )
            {
                // add a default name claim from the Name identifier claim.
                identity.AddClaim( new Claim( DefaultNameClaimType, tokenProperties[key], ClaimValueTypes.String, normalizedIssuer ) );
            }
        }
    }

    return identity;
}

O código a seguir mostra o ValidateSignature método que é invocado a partir da substituição do ValidateToken método no manipulador simples de token da Web.The following code shows ValidateSignature method that is invoked from the override of the ValidateToken method in the simple web token handler. Esse método valida a assinatura no token usando o configurado IssuerTokenResolver .This method validates the signature on the token by using the configured IssuerTokenResolver. O código é extraído do CustomToken exemplo.The code is taken from the CustomToken sample. Para obter informações sobre esse exemplo e outros exemplos disponíveis para o WIF e onde baixá-los, consulte o índice de exemplo de código do WIF.For information about this sample and other samples available for WIF and where to download them, see WIF Code Sample Index.

/// <summary>
/// Validates the signature on the incoming token.
/// </summary>
/// <param name="simpleWebToken">The incoming <see cref="SimpleWebToken"/>.</param>
protected virtual void ValidateSignature( SimpleWebToken simpleWebToken )
{
    if ( simpleWebToken == null )
    {
        throw new ArgumentNullException( "simpleWebToken" );
    }

    if ( String.IsNullOrEmpty( simpleWebToken.SerializedToken ) || String.IsNullOrEmpty( simpleWebToken.Signature ) )
    {
        throw new SecurityTokenValidationException( "The token does not have a signature to verify" );
    }

    string serializedToken = simpleWebToken.SerializedToken;           
    string unsignedToken = null;

    // Find the last parameter. The signature must be last per SWT specification.
    int lastSeparator = serializedToken.LastIndexOf( ParameterSeparator );

    // Check whether the last parameter is an hmac.
    if ( lastSeparator > 0 )
    {
        string lastParamStart = ParameterSeparator + SimpleWebTokenConstants.Signature + "=";
        string lastParam = serializedToken.Substring( lastSeparator );

        // Strip the trailing hmac to obtain the original unsigned string for later hmac verification.               
        if ( lastParam.StartsWith( lastParamStart, StringComparison.Ordinal ) )
        {
            unsignedToken = serializedToken.Substring( 0, lastSeparator );
        }
    }

    SimpleWebTokenKeyIdentifierClause clause = new SimpleWebTokenKeyIdentifierClause(simpleWebToken.Audience);
    InMemorySymmetricSecurityKey securityKey = null;
    try
    {
        securityKey = (InMemorySymmetricSecurityKey)this.Configuration.IssuerTokenResolver.ResolveSecurityKey(clause);
    }
    catch (InvalidOperationException)
    {
        throw new SecurityTokenValidationException( "A Symmetric key was not found for the given key identifier clause.");
    }

    string generatedSignature = GenerateSignature( unsignedToken, securityKey.GetSymmetricKey() );

    if ( string.CompareOrdinal( generatedSignature, simpleWebToken.Signature ) != 0 )
    {
        throw new SecurityTokenValidationException( "The signature on the incoming token is invalid.") ;
    }
}
/// <summary>
/// Generates an HMACSHA256 signature for a given string and key.
/// </summary>
/// <param name="unsignedToken">The token to be signed.</param>
/// <param name="signingKey">The key used to generate the signature.</param>
/// <returns>The generated signature.</returns>
protected static string GenerateSignature(string unsignedToken, byte[] signingKey)
{
    using (HMACSHA256 hmac = new HMACSHA256(signingKey))
    {
        byte[] signatureBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken));
        string signature = HttpUtility.UrlEncode(Convert.ToBase64String(signatureBytes));

        return signature;
    }
}

O código a seguir mostra o ValidateAudience método que é invocado a partir da substituição do ValidateToken método no manipulador simples de token da Web.The following code shows ValidateAudience method that is invoked from the override of the ValidateToken method in the simple web token handler. Esse método valida o público contido no token em relação aos URIs de público que foram especificados na configuração.This method validates the audience contained in the token against the audience URIs that were specified in configuration. O código é extraído do CustomToken exemplo.The code is taken from the CustomToken sample. Para obter informações sobre esse exemplo e outros exemplos disponíveis para o WIF e onde baixá-los, consulte o índice de exemplo de código do WIF.For information about this sample and other samples available for WIF and where to download them, see WIF Code Sample Index.

/// <summary>
/// Validates the audience of the incoming token with those specified in configuration.
/// </summary>
/// <param name="tokenAudience">The audience of the incoming token.</param>
protected virtual void ValidateAudience( string tokenAudience )
{
    if ( Configuration.AudienceRestriction.AudienceMode != AudienceUriMode.Never )
    {
        if ( String.IsNullOrEmpty( tokenAudience ) )
        {
            throw new SecurityTokenValidationException("The incoming token does not have a valid audience Uri and the Audience Restriction is not set to 'None'.");
        }

        if ( Configuration.AudienceRestriction.AllowedAudienceUris.Count == 0 )
        {
            throw new InvalidOperationException( " Audience Restriction is not set to 'None' but no valid audience URI's are configured." );
        }

        IList<Uri> allowedAudienceUris = Configuration.AudienceRestriction.AllowedAudienceUris;
        
        Uri audienceUri = null;

        Uri.TryCreate(tokenAudience, UriKind.RelativeOrAbsolute, out audienceUri);
        
        // Strip off any query string or fragment. 
        Uri audienceLeftPart;

        if ( audienceUri.IsAbsoluteUri )
        {
            audienceLeftPart = new Uri( audienceUri.GetLeftPart( UriPartial.Path ) );
        }
        else
        {
            Uri baseUri = new Uri( "http://www.example.com" );
            Uri resolved = new Uri( baseUri, tokenAudience );
            audienceLeftPart = baseUri.MakeRelativeUri( new Uri( resolved.GetLeftPart( UriPartial.Path ) ) );
        }

        if ( !allowedAudienceUris.Contains( audienceLeftPart ) )
        {
            throw new AudienceUriValidationFailedException(
                    "The Audience Uri of the incoming token is not present in the list of permitted Audience Uri's.");
        }
    }
}

Comentários

Por padrão, esse método gera uma NotImplementedException exceção.By default this method throws a NotImplementedException exception.

O ValidateToken método é chamado pela infraestrutura para validar e extrair as declarações do token de segurança desserializado.The ValidateToken method is called by the infrastructure to validate and extract the claims from the deserialized security token. Essas declarações são retornadas na coleção de ClaimsIdentity objetos retornada pelo método.These claims are returned in the collection of ClaimsIdentity objects returned by the method. No caso típico, essa coleção conterá uma única identidade.In the typical case, this collection will contain a single identity.

Em classes derivadas, a validação normalmente inclui a validação do público-alvo especificado no token em relação aos URIs de público especificados na SecurityTokenHandlerConfiguration.AudienceRestriction Propriedade do objeto de configuração do manipulador de token especificado na Configuration propriedade.In derived classes, validation typically includes validating the intended audience specified in the token against the audience URIs specified in the SecurityTokenHandlerConfiguration.AudienceRestriction property of the token handler configuration object specified on the Configuration property. Esses URIs normalmente são definidos no arquivo de configuração no elemento < audienceUris > .These URIs are typically set in the configuration file under the <audienceUris> element. Se o público não puder ser validado, uma AudienceUriValidationFailedException exceção deverá ser lançada.If the audience cannot be validated, an AudienceUriValidationFailedException exception should be thrown.

Ao processar o token, o emissor é normalmente validado passando o token do emissor para um dos GetIssuerName métodos no IssuerNameRegistry objeto que está configurado para o manipulador por meio da Configuration propriedade.When processing the token, the issuer is typically validated by passing the issuer token to one of the GetIssuerName methods on the IssuerNameRegistry object that is configured for the handler through the Configuration property. O registro de nome do emissor normalmente é configurado por meio do elemento < IssuerNameRegistry > no arquivo de configuração.The issuer name registry is typically configured through the <issuerNameRegistry> element in the configuration file. O GetIssuerName retorna o nome do emissor.The GetIssuerName returns the name of the issuer. Esse nome deve ser usado para definir a Claim.Issuer propriedade em declarações contidas no token.This name should be used to set the Claim.Issuer property in claims contained in the token. Se o registro de nome do emissor não contiver uma entrada para o token do emissor, o GetIssuerName retornará null .If the issuer name registry does not contain an entry for the issuer token, GetIssuerName returns null. Nesse caso, um SecurityTokenException é normalmente lançado em classes derivadas, mas esse comportamento é até o designer da classe.In this case a SecurityTokenException is typically thrown in derived classes, but this behavior is up to the designer of the class.

Aplica-se a