SecurityTokenHandler.ValidateToken(SecurityToken) Método
Definição
Importante
Algumas informações dizem respeito a um produto pré-lançado que pode ser substancialmente modificado antes de ser lançado. A Microsoft não faz garantias, de forma expressa ou implícita, em relação à informação aqui apresentada.
Quando sobreposto numa classe derivada, valida o token de segurança especificado. O token deve ser do tipo processado pela classe derivada.
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 validar.
Devoluções
As identidades contidas no token.
Exemplos
O código seguinte mostra uma sobreposição do ValidateToken método para um gestor de token de segurança que processa tokens web simples (SWT). O código é retirado do CustomToken exemplo. Para informações sobre esta amostra e outras amostras disponíveis para WIF e onde as descarregar, consulte Índice de Exemplos de Código 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();
}
O código seguinte mostra CreateClaims o método que é invocado a partir da sobreposição do ValidateToken método no exemplo anterior. Este método devolve um ClaimsIdentity objeto criado a partir das reivindicações no token. O código é retirado do CustomToken exemplo. Para informações sobre esta amostra e outras amostras disponíveis para WIF e onde as descarregar, consulte Índice de Exemplos de Código 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;
}
O código seguinte mostra ValidateSignature o método que é invocado a partir da sobreposição ValidateToken do método no simples manipulador de token web. Este método valida a assinatura no token usando a configuração IssuerTokenResolver. O código é retirado do CustomToken exemplo. Para informações sobre esta amostra e outras amostras disponíveis para WIF e onde as descarregar, consulte Índice de Exemplos de Código 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;
}
}
O código seguinte mostra ValidateAudience o método que é invocado a partir da sobreposição ValidateToken do método no simples manipulador de token web. Este método valida a audiência contida no token em relação aos URIs de audiência especificados na configuração. O código é retirado do CustomToken exemplo. Para informações sobre esta amostra e outras amostras disponíveis para WIF e onde as descarregar, consulte Índice de Exemplos de Código 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.");
}
}
}
Observações
Por defeito, este método lança uma NotImplementedException exceção.
O ValidateToken método é chamado pela infraestrutura para validar e extrair as reivindicações do token de segurança desserializado. Estas reivindicações são devolvidas na coleção de ClaimsIdentity objetos devolvidos pelo método. No caso típico, esta coleção conterá uma única identidade.
Em classes derivadas, a validação inclui tipicamente validar o público pretendido especificado no token contra os URIs de audiência especificados na SecurityTokenHandlerConfiguration.AudienceRestriction propriedade do objeto de configuração do handler do token especificado na Configuration propriedade. Estes URIs são normalmente definidos no ficheiro de configuração sob o <elemento audienceUris> . Se o público não puder ser validado, deve ser lançada uma AudienceUriValidationFailedException exceção.
Ao processar o token, o emissor é normalmente validado ao passar o token do emissor para um dos GetIssuerName métodos no IssuerNameRegistry objeto configurados para o handler através da Configuration propriedade. O registo de nomes do emissor é normalmente configurado através do <elemento issuerNameRegistry> no ficheiro de configuração. Devolve GetIssuerName o nome do emitente. Este nome deve ser usado para definir a Claim.Issuer propriedade nas reivindicações contidas no token. Se o registo de nomes do emissor não contiver uma entrada para o token do emissor, GetIssuerName devolve null. Neste caso, a SecurityTokenException é normalmente inserido em classes derivadas, mas este comportamento cabe ao designer da classe.