Tokens in java with example

JSON Web Token (JWT) — пример Java реализации на Spring Boot OAuth2 Resource Server 6.0

Часть 2-я по открытому занятию нового учебного курса: реализация простого JWT через новый Spring Boot OAuth2 Resource Server (первая часть: Spring Boot 3.0 — готовимся заранее). Что такое JWT и зачем, писать здесь не буду — в сети материалов много, начинать знакомство обычно рекомендую с Википедии. А вот хорошая ссылка по реализации JWT+OAuth2. Здесь я привожу Java код, основанный на официальном примере spring-projects — простейшей реализации JWT Login Sample (без refresh token и отдельного авторизационного сервера), «творчески доработанный» и с моими пояснениями. Еще раз — без теории, для тех, кому интересен код актуальной Java реализации. Если это Вы — прошу к прочтению.

Чтобы не повторять каждый раз основы, курс стартует с финального кода открытого проекта Spring Boot 2.x + HATEOAS: Basic аутентификация и авторизация на основе ролей, регистрация пользователя в приложении, управление своим профилем и администрирование пользователей (код на GitHub). Реализация добавления JWT аутентификации находится в ветке patched другого репозитория, начиная с 3го комита. Для разбора кода проще всего вычекать его к себе:

git clone —branch patched https://github.com/JavaOPs/cloudjava

Комит 1_03_jwt_token: реализуем получение JWT токена

Для большей безопасности будем использовать ассиметричные RS256 ключи: проверить подлинность токена может любой, а подписать его только тот, у кого есть приватный ключ. Ключи можно взять мои или заменить их своими (generate PKCS#8 private key with openssl):

openssl genpkey -out jwt.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048 - приватный ключ в формате PKCS8писи openssl rsa -in jwt.pem -pubout -out jwt.pub - публичный ключ для декодирования
  • Поместим ключи в \src\main\resources\keys
  • Добавляем зависимость org.springframework.boot:spring-boot-starter-oauth2-resource-server
  • Объявляем ключи в application.yaml и инжектим в JwtSecurityConfiguration . С помощью ключей создаем бины JwtDecoder/JwtEncoder
  • SecurityConfiguration переименовываем в LoginSecurityConfiguration . httpBasic будем использовать только для получения JWT
  • Создаем TokenController , где генерируем JWT. Детали залогиненного пользователя AuthUser добавляю в JWT в отдельном JwtUtil#addUserDetails
  • «Выключаем» тесты через Junit5 @Disabled
Читайте также:  Python read csv to numpy

Перед сборкой не забываем gradle clean. Проверяем получение JWT:

### JetBrains Tools->HTTP Client POST http://localhost:8080/token Authorization: Basic admin@javaops.ru admin

В ответ получаем длинную строке типа eyJhbGciOiJSUzI1NiJ9.. .Она хорошо копируется из JetBrains HTTP Client. В Unix можно сделать export , который можно использовать после следующего комита:

export JWT=`curl -XPOST -u admin@javaops.ru:admin localhost:8080/token`

1_04_jwt_api: переводим API на JWT:

  • Добавляем JwtUser , которого будем получать после JWT аутентификации из JwtUtil#createJwtUser . Функционал по добавлению деталей пользователя в JWT и извлечению их должен находиться рядом.
  • Добавляем в JwtSecurityConfiguration вторую конфигурацию AAA по JWT (порядок фильтров не важен). Конвертируем стандартный JwtAuthenticationToken в JwtUser .
  • В методы ProfileController инжектим наш principal object JwtUser (с @AuthenticationPrincipal у меня не работает). В случае, когда для функционала необходим пользователь, достаем его из базы: AbstractUserController#findByJwtUser (не обязательно это делать для всех методов API).
  • В SecurityContext при обращении к API теперь попадает объект JwtUser , рефакторим SecurityUtil

gradle clean и проверяем API: полученный JWT вставляем вместо [JWT_TOKEN]:

GET http://localhost:8080/api/profile Authorization: Bearer [JWT_TOKEN] или curl -H "Authorization: Bearer $JWT" localhost:8080/api/profile

1_05_jwt_test: восстанавливаем тесты

Как вариант можно воспользоваться jwt() подменой. Но я делаю все честно, с получением токена:

  • В AbstractControllerTest добавляем вспомогательные методы getJWT с Basic авторизацией
  • Добавляем тесты на получения JWT: TokenControllerTest
  • Для API добавляем вспомогательный AbstractControllerTest#performJwt с аторизационным Bearer заголовком. Чтобы токены не перезапрашивать в каждом тесте, кэшируем их в AbstractControllerTest#userJwtMap (синхронизация не нужна — не проблема, если даже они перевычислятся несколько раз)
  • Рефакторим тесты API с использованием этих методов. Где нет авторизации, остаются старые методы perform

Проверяемся: gradle test

Код открытый, можно модифицировать. Ссылка на источник не обязательна, но, если сделаете, буду признателен:) Если код нравится — проголосуйте «за», если нет — напишите замечание в комментарии. Если вы ждали объяснений работы JWT — не надо минусовать статью — вы плохо прочли аннотацию к ней.

Источник

JSON Web Token in Java using Auth0 Java JWT Library

In this Java tutorial, we learn how to work with JSON Web Token (JWT) in Java application using the Auth0’s Java JWT library.

How to add Java JWT Library to your Java project

To use the Java JWT library in the Gradle build project, add the following dependency into the build.gradle file.

implementation 'com.auth0:java-jwt:3.14.0'

To use the Java JWT library in the Maven build project, add the following dependency into the pom.xml file.

Читайте также:  Css courses online free

To have more information about the Java JWT library you can visit the library home page at github.com/auth0/java-jwt

How to generate a new JSON web token

In the following example, we generate a new JSON web token with 2 claim values username and role.

import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; public class GenerateJWTExample  public static void main(String. args)  String secret = "123@abc"; Algorithm algorithm = Algorithm.HMAC512(secret); String generatedToken = JWT.create() .withIssuer("Simple Solution") .withClaim("username", "TestUser") .withClaim("role", "User") .sign(algorithm); System.out.println(generatedToken); > >
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiVXNlciIsImlzcyI6IlNpbXBsZSBTb2x1dGlvbiIsInVzZXJuYW1lIjoiVGVzdFVzZXIifQ.jQUKIOxN0KGbIGJx8SU3WfSVPNASOnRtt3DcoMVBeThcWGzEBAnwlHHYRvbzuas-sOeWSvOwrnsvpQ5tywAfWA

In the following Java program, we learn to generate a JWT token that will expire in 1 minute.

import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import java.util.Date; public class GenerateJWTWithExpireExample  public static void main(String. args)  String secret = "123@abc"; Algorithm algorithm = Algorithm.HMAC512(secret); long expireTime = (new Date().getTime()) + 60000; // 60000 milliseconds = 60 seconds = 1 minute Date expireDate = new Date(expireTime); String generatedToken = JWT.create() .withIssuer("Simple Solution") .withClaim("username", "TestUser") .withClaim("role", "User") .withExpiresAt(expireDate) .sign(algorithm); System.out.println(generatedToken); > >
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiVXNlciIsImlzcyI6IlNpbXBsZSBTb2x1dGlvbiIsImV4cCI6MTYxNjA4MDAzOCwidXNlcm5hbWUiOiJUZXN0VXNlciJ9.S96EHjYKfWfB4TEXqUBfIJVOEBkOWD9wd37OhIJ4TcxTND9Igni0pHiMB-i3efxSaiiQEGvi-pMrwGKISue1MA

How to verify the a JSON web token

Verify the token without expiration date time.

import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTVerificationException; import com.auth0.jwt.interfaces.DecodedJWT; public class VerifyJWTExample  public static void main(String. args)  String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiVXNlciIsImlzcyI6IlNpbXBsZSBTb2x1dGlvbiIsInVzZXJuYW1lIjoiVGVzdFVzZXIifQ.jQUKIOxN0KGbIGJx8SU3WfSVPNASOnRtt3DcoMVBeThcWGzEBAnwlHHYRvbzuas-sOeWSvOwrnsvpQ5tywAfWA"; String secret = "123@abc"; Algorithm algorithm = Algorithm.HMAC512(secret); try  JWTVerifier verifier = JWT.require(algorithm) .withIssuer("Simple Solution") .build(); DecodedJWT decodedJWT = verifier.verify(token); System.out.println("Verify JWT token success."); System.out.println("Claims: " + decodedJWT.getClaims()); > catch (JWTVerificationException ex)  System.out.println("Verify JWT token fail: " + ex.getMessage()); > > >
Verify JWT token success. Claims:

Verify the token with expiration date time.

import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTVerificationException; import com.auth0.jwt.interfaces.DecodedJWT; public class VerifyJWTWithExpireExample  public static void main(String. args)  String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiVXNlciIsImlzcyI6IlNpbXBsZSBTb2x1dGlvbiIsImV4cCI6MTYxNjA4MDEyMCwidXNlcm5hbWUiOiJUZXN0VXNlciJ9.bw87xWcl23Nefzeilnww84kUxvz3Yal90Va6DQogsRhVWvZe_TvmzFkib4ecIKbScMCQnR4a-w3JfaKBw7btNw"; String secret = "123@abc"; Algorithm algorithm = Algorithm.HMAC512(secret); try  JWTVerifier verifier = JWT.require(algorithm) .withIssuer("Simple Solution") .acceptExpiresAt(60) // 60 seconds = 1 minute .build(); DecodedJWT decodedJWT = verifier.verify(token); System.out.println("Verify JWT token success."); System.out.println(decodedJWT.getClaims()); > catch (JWTVerificationException ex)  System.out.println("Verify JWT token fail: " + ex.getMessage()); > > >

How to decode a given JSON web token

In the following Java program, we learn how to decode a given JSON web token and show its issuer and claims data.

import com.auth0.jwt.JWT; import com.auth0.jwt.interfaces.DecodedJWT; public class DecodeJWTExample  public static void main(String. args)  String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiVXNlciIsImlzcyI6IlNpbXBsZSBTb2x1dGlvbiIsInVzZXJuYW1lIjoiVGVzdFVzZXIifQ.jQUKIOxN0KGbIGJx8SU3WfSVPNASOnRtt3DcoMVBeThcWGzEBAnwlHHYRvbzuas-sOeWSvOwrnsvpQ5tywAfWA"; DecodedJWT decodedJWT = JWT.decode(token); System.out.println("Issuer: " + decodedJWT.getIssuer()); System.out.println("Claims: " + decodedJWT.getClaims()); > >
Issuer: Simple Solution Claims:

Implement a reusable JWTService class

At this step, we learn how to implement a reusable class to generate, verify and decode JSON web tokens that can reuse for your Java project.

import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTVerificationException; import com.auth0.jwt.interfaces.DecodedJWT; import java.util.Date; public class JWTService  private long DEFAULT_EXPIRE_IN_SECONDS = 60; private String secret = "123@abc"; private Algorithm algorithm = Algorithm.HMAC256(secret); public String generateJWTToken(String username, String role)  long now = new Date().getTime(); long expireTime = now + (DEFAULT_EXPIRE_IN_SECONDS * 1000); Date expireDate = new Date(expireTime); String jwtToken = JWT.create() .withIssuer("Simple Solution") .withClaim("username", username) .withClaim("role", role) .withExpiresAt(expireDate) .sign(algorithm); return jwtToken; > public boolean verifyJWTToken(String token)  try  JWTVerifier verifier = JWT.require(algorithm) .withIssuer("Simple Solution") .acceptExpiresAt(DEFAULT_EXPIRE_IN_SECONDS) .build(); verifier.verify(token); return true; > catch (JWTVerificationException ex)  return false; > > public String getClaimFromToken(String token, String claimKey)  DecodedJWT decodedJWT = JWT.decode(token); return decodedJWT.getClaims().get(claimKey).toString(); > >

Example program how to use JWTService class.

public class JWTExamples  public static void main(String[] args)  JWTService jwtService = new JWTService(); String token = jwtService.generateJWTToken("TestUser", "User"); boolean result = jwtService.verifyJWTToken(token); System.out.println("Generated Token: " + token); System.out.println("Verify Result: " + result); System.out.println("Token Claim, username: " + jwtService.getClaimFromToken(token, "username")); System.out.println("Token Claim, role: " + jwtService.getClaimFromToken(token, "role")); > >
Generated Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiVXNlciIsImlzcyI6IlNpbXBsZSBTb2x1dGlvbiIsImV4cCI6MTYxNjA4MDM0MywidXNlcm5hbWUiOiJUZXN0VXNlciJ9.4NLv-75XG-uyz-3YjnuRau7aKOOUagJ9szdWDR-OR7k Verify Result: true Token Claim, username: "TestUser" Token Claim, role: "User"

Conclusion

In this Java JSON web token tutorial, we have learned how to use the Java JWT library to generate a new token, verify and decode a given token. We also implement a reusable Java class to reuse for different Java projects.

Источник

Оцените статью