JJWT pretende ser a biblioteca mais fácil de usar e entender para criar e verificar JSON Web Tokens (JWTs) e JSON Web Keys (JWKs) na JVM e Android.
JJWT é uma implementação Java pura baseada exclusivamente nas especificações RFC do JOSE Working Group:
RFC 7519: JSON Web Token (JWT)
RFC 7515: Assinatura Web JSON (JWS)
RFC 7516: criptografia da Web JSON (JWE)
RFC 7517: Chave da Web JSON (JWK)
RFC 7518: Algoritmos Web JSON (JWA)
RFC 7638: impressão digital da chave da Web JSON
RFC 9278: URI de impressão digital da chave da Web JSON
RFC 7797: Opção de carga útil não codificada JWS
RFC 8037: Algoritmos da Curva de Edwards e JWKs
Foi criado por Les Hazlewood e é apoiado e mantido por uma comunidade de colaboradores.
JJWT é de código aberto sob os termos da licença Apache 2.0.
PublicKey
JWK privadatoString()
Totalmente funcional em todos os JDKs Java 7+ e Android
Melhores práticas e afirmações de segurança automáticas
API fácil de aprender e ler
Interfaces fluentes convenientes e legíveis, ótimas para preenchimento automático de IDE para escrever código rapidamente
Totalmente compatível com as especificações RFC em todas as funcionalidades implementadas, testadas em relação a vetores de teste especificados por RFC
Implementação estável com quase 1.700 testes e 100% de cobertura de código de teste. Cada método, instrução e variante de ramificação condicional em toda a base de código é testado e necessário para ser transmitido em cada construção.
Criação, análise e verificação de JWTs compactos assinados digitalmente (também conhecidos como JWSs) com todos os algoritmos JWS padrão:
Identificador | Algoritmo de Assinatura |
---|---|
| HMAC usando SHA-256 |
| HMAC usando SHA-384 |
| HMAC usando SHA-512 |
| ECDSA usando P-256 e SHA-256 |
| ECDSA usando P-384 e SHA-384 |
| ECDSA usando P-521 e SHA-512 |
| RSASSA-PKCS-v1_5 usando SHA-256 |
| RSASSA-PKCS-v1_5 usando SHA-384 |
| RSASSA-PKCS-v1_5 usando SHA-512 |
| RSASSA-PSS usando SHA-256 e MGF1 com SHA-256 1 |
| RSASSA-PSS usando SHA-384 e MGF1 com SHA-384 1 |
| RSASSA-PSS usando SHA-512 e MGF1 com SHA-512 1 |
| Algoritmo 2 de assinatura digital de curva de Edwards |
1. Requer Java 11 ou um provedor JCA compatível (como BouncyCastle) no caminho de classe do tempo de execução.
2 . Requer Java 15 ou um provedor JCA compatível (como BouncyCastle) no caminho de classe do tempo de execução.
Criação, análise e descriptografia de JWTs compactos criptografados (também conhecidos como JWEs) com todos os algoritmos de criptografia JWE padrão:
Identificador | Algoritmo de criptografia |
---|---|
| Algoritmo de criptografia autenticado AES_128_CBC_HMAC_SHA_256 |
| Algoritmo de criptografia autenticado AES_192_CBC_HMAC_SHA_384 |
| Algoritmo de criptografia autenticado AES_256_CBC_HMAC_SHA_512 |
| AES GCM usando chave 1 de 128 bits |
| AES GCM usando chave 1 de 192 bits |
| AES GCM usando chave 1 de 256 bits |
1 . Requer Java 8 ou um provedor JCA compatível (como BouncyCastle) no caminho de classe do tempo de execução.
Todos os algoritmos de gerenciamento de chaves para obter chaves de criptografia e descriptografia JWE:
Identificador | Algoritmo de gerenciamento de chaves |
---|---|
| RSAES-PKCS1-v1_5 |
| RSAES OAEP usando parâmetros padrão |
| RSAES OAEP usando SHA-256 e MGF1 com SHA-256 |
| AES Key Wrap com valor inicial padrão usando chave de 128 bits |
| AES Key Wrap com valor inicial padrão usando chave de 192 bits |
| AES Key Wrap com valor inicial padrão usando chave de 256 bits |
| Uso direto de uma chave simétrica compartilhada como CEK |
| Curva elíptica Diffie-Hellman Ephemeral Acordo de chave estática usando Concat KDF |
| ECDH-ES usando Concat KDF e CEK embalado com "A128KW" |
| ECDH-ES usando Concat KDF e CEK embalado com "A192KW" |
| ECDH-ES usando Concat KDF e CEK embalado com "A256KW" |
| Quebra de chave com AES GCM usando chave 1 de 128 bits |
| Quebra de chave com AES GCM usando chave 1 de 192 bits |
| Quebra de chave com AES GCM usando chave 1 de 256 bits |
| PBES2 com HMAC SHA-256 e embalagem "A128KW" 1 |
| PBES2 com HMAC SHA-384 e embalagem "A192KW" 1 |
| PBES2 com HMAC SHA-512 e embalagem "A256KW" 1 |
1 . Requer Java 8 ou um provedor JCA compatível (como BouncyCastle) no caminho de classe do tempo de execução.
Criação, análise e verificação de JSON Web Keys (JWKs) em todos os formatos de chave JWA padrão usando tipos Key
Java nativos:
Formato de chave JWK | Tipo Key Java | JJWT Tipo Jwk |
---|---|---|
Chave Simétrica | | |
Chave pública de curva elíptica | | |
Chave privada da curva elíptica | | |
Chave Pública RSA | | |
Chave privada RSA | | |
Chave privada XDH | | |
Chave privada XDH | | |
Chave pública EdDSA | | |
Chave privada EdDSA | | |
1 . Requer Java 15 ou um provedor JCA compatível (como BouncyCastle) no caminho de classe do tempo de execução.
2 . Requer Java 15 ou um provedor JCA compatível (como BouncyCastle) no caminho de classe do tempo de execução.
Aprimoramentos de conveniência além das especificações, como
Compressão de carga útil para qualquer JWT grande, não apenas JWEs
Asserções de declarações (exigindo valores específicos)
Reivindique empacotamento e desempacotamento de POJO ao usar um analisador JSON compatível (por exemplo, Jackson)
Geração de chave segura com base nos algoritmos JWA desejados
e mais…
Serialização e análise não compacta.
Este recurso poderá ser implementado em uma versão futura. Contribuições da comunidade são bem-vindas!
Se você tiver problemas ao usar o JJWT, leia primeiro a documentação nesta página antes de fazer perguntas. Nós nos esforçamos ao máximo para garantir que a documentação do JJWT seja robusta, categorizada com um índice e atualizada para cada versão.
Se a documentação ou a API JavaDoc não for suficiente e você tiver dúvidas de usabilidade ou estiver confuso sobre alguma coisa, faça sua pergunta aqui. No entanto:
Por favor, não crie um problema no GitHub para fazer uma pergunta.
Usamos GitHub Issues para rastrear trabalhos acionáveis que exigem alterações no design e/ou base de código do JJWT. Se você tiver alguma dúvida sobre usabilidade, faça sua pergunta aqui e podemos convertê-la em um problema, se necessário.
Se for criado um problema no GitHub que não represente um trabalho acionável para a base de código do JJWT, ele será imediatamente fechado.
Se você não tiver dúvidas sobre usabilidade e acreditar que tem um bug legítimo ou uma solicitação de recurso, discuta-o aqui PRIMEIRO . Por favor, faça uma pesquisa rápida primeiro para ver se já existe uma discussão relacionada à sua e junte-se a essa discussão existente, se necessário.
Se você quiser ajudar a corrigir um bug ou implementar o novo recurso sozinho, leia a seção Contribuição a seguir antes de iniciar qualquer trabalho.
Solicitações pull simples que corrigem qualquer coisa diferente do código principal JJWT (documentação, JavaDoc, erros de digitação, casos de teste, etc.) são sempre apreciadas e têm uma alta probabilidade de serem mescladas rapidamente. Por favor, envie-os!
No entanto, se você quiser ou sentir necessidade de alterar a funcionalidade ou o código principal do JJWT, não emita uma solicitação pull sem iniciar uma nova discussão sobre o JJWT e discutir primeiro as alterações desejadas, antes de começar a trabalhar nela .
Seria uma pena rejeitar sua solicitação pull séria e genuinamente apreciada se ela não estiver alinhada com os objetivos do projeto, expectativas de design ou funcionalidade planejada. Infelizmente, tivemos que rejeitar grandes PRs no passado porque eles estavam fora de sincronia com as expectativas do projeto ou design - tudo porque o autor do PR não consultou a equipe antes de trabalhar em uma solução.
Portanto, crie primeiro uma nova discussão JJWT para discutir, e então poderemos facilmente converter a discussão em um problema e então ver se (ou como) um PR é garantido. Obrigado!
Se você gostaria de ajudar, mas não sabe por onde começar, visite a página Problemas necessários para ajuda e escolha qualquer um deles, e teremos prazer em discutir e responder perguntas nos comentários do problema.
Se algum desses não lhe agrada, não se preocupe! Qualquer ajuda que você gostaria de oferecer será apreciada com base nas advertências acima sobre a contribuição de pull requests. Sinta-se à vontade para discutir ou fazer perguntas primeiro se não tiver certeza. :)
JSON Web Token (JWT) é um formato de mensagens baseado em texto de uso geral para transmissão de informações de forma compacta e segura. Ao contrário da crença popular, o JWT não é útil apenas para enviar e receber tokens de identidade na web – mesmo que esse seja o caso de uso mais comum. JWTs podem ser usados como mensagens para qualquer tipo de dados.
Um JWT em sua forma mais simples contém duas partes:
Os dados primários dentro do JWT, chamados de payload
, e
Um Object
JSON com pares nome/valor que representam metadados sobre a payload
e a própria mensagem, chamados de header
.
Uma payload
JWT pode ser absolutamente qualquer coisa - qualquer coisa que possa ser representada como uma matriz de bytes, como Strings, imagens, documentos, etc.
Mas como um header
JWT é um JSON Object
, faria sentido que uma payload
JWT também pudesse ser um Object
JSON. Em muitos casos, os desenvolvedores gostam que a payload
seja JSON, que representa dados sobre um usuário ou computador ou um conceito de identidade semelhante. Quando usado dessa maneira, a payload
é chamada de objeto JSON Claims
, e cada par nome/valor dentro desse objeto é chamado de claim
- cada informação dentro de 'afirma' algo sobre uma identidade.
E embora seja útil “reivindicar” algo sobre uma identidade, qualquer pessoa pode fazer isso. O importante é que você confie nas afirmações, verificando se elas vêm de uma pessoa ou computador em quem você confia.
Um recurso interessante dos JWTs é que eles podem ser protegidos de várias maneiras. Um JWT pode ser assinado criptograficamente (tornando-o o que chamamos de JWS) ou criptografado (tornando-o um JWE). Isso adiciona uma camada poderosa de verificabilidade ao JWT - um destinatário JWS ou JWE pode ter um alto grau de confiança de que vem de alguém em quem confia, verificando uma assinatura ou descriptografando-a. É esse recurso de verificabilidade que torna o JWT uma boa opção para enviar e receber informações seguras, como declarações de identidade.
Finalmente, JSON com espaço em branco para legibilidade humana é bom, mas não é um formato de mensagem muito eficiente. Portanto, os JWTs podem ser compactados (e até compactados) em uma representação mínima - basicamente strings codificadas em Base64URL - para que possam ser transmitidos pela Web com mais eficiência, como em cabeçalhos HTTP ou URLs.
Depois de ter uma payload
e header
, como eles são compactados para transmissão na Web e como é realmente o JWT final? Vamos percorrer uma versão simplificada do processo com algum pseudocódigo:
Suponha que temos um JWT com um header
JSON e uma carga útil de mensagem de texto simples:
cabeçalho
{ "alg": "nenhum" }
carga útil
O verdadeiro sinal de inteligência não é o conhecimento, mas a imaginação.
Remova todos os espaços em branco desnecessários no JSON:
String header = ' {"alg":"none"} '
String payload = ' The true sign of intelligence is not knowledge but imagination. '
Obtenha os bytes UTF-8 e a codificação Base64URL de cada um:
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedPayload = base64URLEncode( payload . getBytes( " UTF-8 " ) )
Junte o cabeçalho codificado e as declarações com caracteres de ponto final ('.'):
String compact = encodedHeader + ' . ' + encodedPayload + ' . '
A string JWT compact
concatenada final se parece com isto:
eyJhbGciOiJub25lIn0.VGhlIHRydWUgc2lnbiBvZiBpbnRlbGxpZ2VuY2UgaXMgbm90IGtub3dsZWRnZSBidXQgaW1hZ2luYXRpb24u.
Isso é chamado de JWT 'desprotegido' porque nenhuma segurança estava envolvida - nenhuma assinatura digital ou criptografia para 'proteger' o JWT para garantir que ele não possa ser alterado por terceiros.
Se quiséssemos assinar digitalmente o formulário compacto para podermos pelo menos garantir que ninguém altera os dados sem que os detectemos, teríamos que realizar mais alguns passos, mostrados a seguir.
Em vez de uma carga útil de texto simples, o próximo exemplo usará provavelmente o tipo mais comum de carga útil - um Object
de reivindicações JSON contendo informações sobre uma identidade específica. Também assinaremos digitalmente o JWT para garantir que ele não possa ser alterado por terceiros sem nosso conhecimento.
Suponha que temos um header
JSON e uma payload
de declarações:
cabeçalho
{
"alg" : " HS256 "
}
carga útil
{
"sub" : " Joe "
}
Neste caso, o header
indica que o algoritmo HS256
(HMAC usando SHA-256) será utilizado para assinar criptograficamente o JWT. Além disso, o objeto JSON payload
tem uma única declaração, sub
com valor Joe
.
Há uma série de reivindicações padrão, chamadas de Reivindicações Registradas, na especificação e sub
(para 'Assunto') é uma delas.
Remova todos os espaços em branco desnecessários em ambos os objetos JSON:
String header = ' {"alg":"HS256"} '
String claims = ' {"sub":"Joe"} '
Obtenha seus bytes UTF-8 e codificação Base64URL cada:
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedClaims = base64URLEncode( claims . getBytes( " UTF-8 " ) )
Concatene o cabeçalho codificado e as declarações com um caractere de ponto final '.' delimitador:
String concatenated = encodedHeader + ' . ' + encodedClaims
Use um segredo criptográfico ou chave privada suficientemente forte, juntamente com um algoritmo de assinatura de sua escolha (usaremos HMAC-SHA-256 aqui) e assine a string concatenada:
SecretKey key = getMySecretKey()
byte [] signature = hmacSha256( concatenated, key )
Como as assinaturas são sempre matrizes de bytes, codifique a assinatura em Base64URL e junte-a à string concatenated
com um caractere de ponto final '.' delimitador:
String compact = concatenated + ' . ' + base64URLEncode( signature )
E aí está, a String compact
final fica assim:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Isso é chamado de 'JWS' - abreviação de JWT assinado .
É claro que ninguém gostaria de fazer isso manualmente no código e, pior ainda, se você errar alguma coisa, poderá introduzir sérios problemas e fraquezas de segurança. Como resultado, o JJWT foi criado para lidar com tudo isso para você: o JJWT automatiza completamente a criação de JWSs e a análise e verificação de JWSs para você.
Até agora vimos um JWT desprotegido e um JWT assinado criptograficamente (chamado de 'JWS'). Uma das coisas inerentes a ambos é que todas as informações contidas neles podem ser vistas por qualquer pessoa - todos os dados no cabeçalho e na carga útil são visíveis publicamente. O JWS apenas garante que os dados não foram alterados por ninguém - não impede que ninguém os veja. Muitas vezes, isso é bom porque os dados contidos neles não são informações confidenciais.
Mas e se você precisasse representar informações em um JWT que são consideradas informações confidenciais - talvez o endereço postal, o número do seguro social ou o número da conta bancária de alguém?
Nesses casos, queremos um JWT totalmente criptografado, abreviadamente chamado de 'JWE'. Um JWE usa criptografia para garantir que a carga útil permaneça totalmente criptografada e autenticada, de modo que partes não autorizadas não possam ver os dados contidos ou alterá-los sem serem detectados. Especificamente, a especificação JWE exige que algoritmos de criptografia autenticada com dados associados sejam usados para criptografar e proteger totalmente os dados.
Uma visão geral completa dos algoritmos AEAD está fora do escopo desta documentação, mas aqui está um exemplo de um JWE compacto final que utiliza esses algoritmos (as quebras de linha são apenas para facilitar a leitura):
eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0. 6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ. AxY8DCtDaGlsbGljb3RoZQ. KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY. U0m_YmjN04DJvceFICbCVQ
A seguir, abordaremos como instalar o JJWT em seu projeto e, em seguida, veremos como usar a bela API fluente do JJWT em vez da manipulação arriscada de strings para construir JWTs, JWSs e JWEs de forma rápida e segura.
Use sua ferramenta de compilação favorita compatível com Maven para extrair as dependências do Maven Central.
As dependências podem ser um pouco diferentes se você estiver trabalhando com um projeto JDK ou Android.
Se estiver criando um projeto JDK (não Android), você desejará definir as seguintes dependências:
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-api</ artifactId >
< version >0.12.6</ version >
</ dependency >
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-impl</ artifactId >
< version >0.12.6</ version >
< scope >runtime</ scope >
</ dependency >
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-jackson</ artifactId > <!-- or jjwt-gson if Gson is preferred -->
< version >0.12.6</ version >
< scope >runtime</ scope >
</ dependency >
<!-- Uncomment this next dependency if you are using:
- JDK 10 or earlier, and you want to use RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- JDK 10 or earlier, and you want to use EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- JDK 14 or earlier, and you want to use EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
It is unnecessary for these algorithms on JDK 15 or later.
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId> or bcprov-jdk15to18 on JDK 7
<version>1.76</version>
<scope>runtime</scope>
</dependency>
-->
dependencies {
implementation ' io.jsonwebtoken:jjwt-api:0.12.6 '
runtimeOnly ' io.jsonwebtoken:jjwt-impl:0.12.6 '
runtimeOnly ' io.jsonwebtoken:jjwt-jackson:0.12.6 ' // or 'io.jsonwebtoken:jjwt-gson:0.12.6' for gson
/*
Uncomment this next dependency if you are using:
- JDK 10 or earlier, and you want to use RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- JDK 10 or earlier, and you want to use EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- JDK 14 or earlier, and you want to use EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
It is unnecessary for these algorithms on JDK 15 or later.
*/
// runtimeOnly 'org.bouncycastle:bcprov-jdk18on:1.76' // or bcprov-jdk15to18 on JDK 7
}
Os projetos Android desejarão definir as seguintes dependências e exclusões do Proguard e o BouncyCastle Provider
opcional:
Adicione as dependências ao seu projeto:
dependencies {
api( ' io.jsonwebtoken:jjwt-api:0.12.6 ' )
runtimeOnly( ' io.jsonwebtoken:jjwt-impl:0.12.6 ' )
runtimeOnly( ' io.jsonwebtoken:jjwt-orgjson:0.12.6 ' ) {
exclude( group : ' org.json ' , module : ' json ' ) // provided by Android natively
}
/*
Uncomment this next dependency if you want to use:
- RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
** AND ALSO ensure you enable the BouncyCastle provider as shown below **
*/
// implementation('org.bouncycastle:bcprov-jdk18on:1.76') // or bcprov-jdk15to18 for JDK 7
}
Você pode usar as seguintes regras de exclusão do Android Proguard:
-keepattributesInnerClasses -manter classe io.jsonwebtoken.** { *; } -keepnames classe io.jsonwebtoken.* { *; } -keepnames interface io.jsonwebtoken.* { *; } -keep class org.bouncycastle.** { *; } -keepnames class org.bouncycastle.** { *; } -dontwarn org.bouncycastle.**
Se você deseja usar algoritmos JWT RSASSA-PSS (ou seja, PS256
, PS384
e PS512
), EdECDH ( X25512
ou X448
), criptografia Elliptic Curve Diffie-Hellman, algoritmos de assinatura EdDSA ( Ed25519
ou Ed448
), ou você apenas deseja garantir seu Android aplicativo estiver executando uma versão atualizada do BouncyCastle, você precisará:
Remova o comentário da dependência BouncyCastle conforme comentado acima na seção de dependências.
Substitua o provedor BC
personalizado do Android herdado pelo atualizado.
O registro do provedor precisa ser feito no início do ciclo de vida da aplicação, preferencialmente na classe Activity
principal da sua aplicação como um bloco de inicialização estático. Por exemplo:
class MainActivity : AppCompatActivity () {
companion object {
init {
Security .removeProvider( " BC " ) // remove old/legacy Android-provided BC provider
Security .addProvider( BouncyCastleProvider ()) // add 'real'/correct BC provider
}
}
// ... etc ...
}
Observe que todas as declarações de dependência JJWT acima têm apenas uma dependência de tempo de compilação e o restante é declarado como dependências de tempo de execução .
Isso ocorre porque o JJWT foi projetado para que você dependa apenas das APIs explicitamente projetadas para uso em seus aplicativos e todos os outros detalhes internos de implementação - que podem mudar sem aviso prévio - são relegados a dependências somente de tempo de execução. Este é um ponto extremamente importante se você deseja garantir o uso e atualizações estáveis do JJWT ao longo do tempo:
JJWT garante compatibilidade de versão semântica para todos os seus artefatos, exceto o |
Isso é feito para beneficiá-lo: é preciso muito cuidado na curadoria do jjwt-api
.jar e na garantia de que ele contém o que você precisa e permanece compatível com versões anteriores tanto quanto possível, para que você possa confiar nisso com segurança com o escopo de compilação. A estratégia de tempo de execução jjwt-impl
.jar oferece aos desenvolvedores JJWT a flexibilidade para alterar os pacotes e implementações internas quando e como for necessário. Isso nos ajuda a implementar recursos, corrigir bugs e enviar novos lançamentos para você com mais rapidez e eficiência.
A maior parte da complexidade está escondida atrás de uma interface fluente baseada em construtor conveniente e legível, ótima para contar com o preenchimento automático do IDE para escrever código rapidamente. Aqui está um exemplo:
import io . jsonwebtoken . Jwts ;
import io . jsonwebtoken . security . Keys ;
import java . security . Key ;
// We need a signing key, so we'll create one just for this example. Usually
// the key would be read from your application configuration instead.
SecretKey key = Jwts . SIG . HS256 . key (). build ();
String jws = Jwts . builder (). subject ( "Joe" ). signWith ( key ). compact ();
Quão fácil foi isso!?
Neste caso, somos:
construindo um JWT que terá o sub
(Assunto) da declaração registrada definido como Joe
. Estamos então
assinar o JWT usando uma chave adequada para o algoritmo HMAC-SHA-256. Finalmente, estamos
compactando- o em sua forma String
final. Um JWT assinado é chamado de 'JWS'.
A string jws
resultante fica assim:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Agora vamos verificar o JWT (você deve sempre descartar JWTs que não correspondam à assinatura esperada):
assert Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( jws ). getPayload (). getSubject (). equals ( "Joe" );
Há duas coisas acontecendo aqui. A key
anterior está sendo usada para verificar a assinatura do JWT. Se não conseguir verificar o JWT, uma SignatureException
(que estende JwtException
) será lançada. Supondo que o JWT seja verificado, analisamos as declarações e afirmamos que esse assunto está definido como Joe
. Você tem que adorar frases curtas de código que impressionam!
OBSERVAÇÃO | JWTs com segurança de tipo: para obter um resultado JWT |
Mas e se a análise ou a validação da assinatura falharem? Você pode capturar JwtException
e reagir de acordo:
try {
Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( compactJws );
//OK, we can trust this JWT
} catch ( JwtException e ) {
//don't trust the JWT!
}
Agora que tivemos uma 'amostra' de início rápido de como criar e analisar JWTs, vamos abordar a API do JJWT em detalhes.
Você cria um JWT da seguinte maneira:
Use o método Jwts.builder()
para criar uma instância JwtBuilder
.
Opcionalmente, defina quaisquer parâmetros header
conforme desejado.
Chame métodos de construtor para definir o conteúdo ou as declarações da carga útil.
Opcionalmente, chame os métodos signWith
ou encryptWith
se desejar assinar ou criptografar digitalmente o JWT.
Chame o método compact()
para produzir a string JWT compacta resultante.
Por exemplo:
String jwt = Jwts . builder () // (1)
. header () // (2) optional
. keyId ( "aKeyId" )
. and ()
. subject ( "Bob" ) // (3) JSON Claims, or
//.content(aByteArray, "text/plain") // any byte[] content, with media type
. signWith ( signingKey ) // (4) if signing, or
//.encryptWith(key, keyAlg, encryptionAlg) // if encrypting
. compact (); // (5)
A payload
JWT pode ser byte[]
content (via content
) ou JSON Claims (como subject
, claims
, etc), mas não ambos.
Assinaturas digitais ( signWith
) ou criptografia ( encryptWith
) podem ser usadas, mas não ambas.
JWTs desprotegidos : se você não usar os métodos construtores |
Um cabeçalho JWT é um Object
JSON que fornece metadados sobre o conteúdo, formato e quaisquer operações criptográficas relevantes para a payload
do JWT. JJWT fornece várias maneiras de definir o cabeçalho inteiro e/ou vários parâmetros de cabeçalho individuais (pares nome/valor).
A maneira mais fácil e recomendada de definir um ou mais parâmetros de cabeçalho JWT (pares nome/valor) é usar o construtor header()
do JwtBuilder
conforme desejado e, em seguida, chamar seu método and()
para retornar ao JwtBuilder
para configuração adicional . Por exemplo:
String jwt = Jwts . builder ()
. header () // <----
. keyId ( "aKeyId" )
. x509Url ( aUri )
. add ( "someName" , anyValue )
. add ( mapValues )