Condividi tramite


SecurityTokenHandler.ValidateToken(SecurityToken) Metodo

Definizione

Una volta eseguito l'override in una classe derivata, convalida il token di sicurezza specificato. Il token deve essere del tipo elaborato dalla classe derivata.

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)

Parametri

token
SecurityToken

Token da convalidare.

Restituisce

Identità contenute nel token.

Esempio

Il codice seguente mostra un override del ValidateToken metodo per un gestore di token di sicurezza che elabora token Web semplici (SWT). Il codice viene tratto dall'esempio CustomToken . Per informazioni su questo esempio e altri esempi disponibili per WIF e dove scaricarli, vedere Indice di esempio di codice WIF.

/// <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();
}

Nel codice seguente viene illustrato CreateClaims il metodo richiamato dall'override del ValidateToken metodo nell'esempio precedente. Questo metodo restituisce un ClaimsIdentity oggetto creato dalle attestazioni nel token. Il codice viene tratto dall'esempio CustomToken . Per informazioni su questo esempio e altri esempi disponibili per WIF e dove scaricarli, vedere Indice di esempio di codice WIF.

/// <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;
}

Il codice seguente mostra ValidateSignature il metodo richiamato dall'override del ValidateToken metodo nel gestore di token Web semplice. Questo metodo convalida la firma nel token usando l'oggetto configurato IssuerTokenResolver. Il codice viene tratto dall'esempio CustomToken . Per informazioni su questo esempio e altri esempi disponibili per WIF e dove scaricarli, vedere Indice di esempio di codice WIF.

/// <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;
    }
}

Il codice seguente mostra ValidateAudience il metodo richiamato dall'override del ValidateToken metodo nel gestore di token Web semplice. Questo metodo convalida il gruppo di destinatari contenuto nel token rispetto agli URI del gruppo di destinatari specificati nella configurazione. Il codice viene tratto dall'esempio CustomToken . Per informazioni su questo esempio e altri esempi disponibili per WIF e dove scaricarli, vedere Indice di esempio di codice WIF.

/// <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.");
        }
    }
}

Commenti

Per impostazione predefinita, questo metodo genera un'eccezione NotImplementedException .

Il ValidateToken metodo viene chiamato dall'infrastruttura per convalidare ed estrarre le attestazioni dal token di sicurezza deserializzato. Queste attestazioni vengono restituite nella raccolta di ClaimsIdentity oggetti restituiti dal metodo . Nel caso tipico, questa raccolta conterrà una singola identità.

Nelle classi derivate, la convalida include in genere la convalida del gruppo di destinatari previsto specificato nel token rispetto agli URI del gruppo di destinatari specificati nella SecurityTokenHandlerConfiguration.AudienceRestriction proprietà dell'oggetto di configurazione del gestore di token specificato nella Configuration proprietà . Questi URI vengono in genere impostati nel file di configurazione nell'elemento <audienceUris> . Se il gruppo di destinatari non può essere convalidato, deve essere generata un'eccezione AudienceUriValidationFailedException .

Quando si elabora il token, l'autorità emittente viene in genere convalidata passando il token dell'autorità di certificazione a uno dei GetIssuerName metodi sull'oggetto IssuerNameRegistry configurato per il gestore tramite la Configuration proprietà . Il registro dei nomi dell'autorità emittente viene in genere configurato tramite l'elemento <issuerNameRegistry> nel file di configurazione. Restituisce GetIssuerName il nome dell'emittente. Questo nome deve essere usato per impostare la Claim.Issuer proprietà nelle attestazioni contenute nel token. Se il registro dei nomi dell'autorità emittente non contiene una voce per il token dell'autorità emittente, GetIssuerName restituisce null. In questo caso un SecurityTokenException oggetto viene in genere generato nelle classi derivate, ma questo comportamento spetta alla finestra di progettazione della classe .

Si applica a