Проверка JWT — Java17 Spring Security JWT: 0.12.6

Я делаю личный проект и пытаюсь настроить API с несколькими конечными точками, защищенными JWT. Я понятия не имел, как работает Spring Security, поэтому решил посмотреть руководство. В итоге у меня появилась конечная точка входа в систему, которая работает. Тем не менее, я пытаюсь получить доступ к конечным точкам, защищенным JWT, с помощью JWT, и он возвращает HTTP-ответ 401 и выдает эту ошибку:

Невозможно проверить подпись JWS: невозможно найти ключ проверки подписи для JWS с заголовком: {alg=HS512}

И вот мой класс:

@Component
public class JWTGenerator {

    @Value("${jwt.secret}")
    private String jwtSecret;

    public String generateToken(Authentication authentication) {
        String email = authentication.getName();
        Date currentDate = new Date();
        Date expireDate = new Date(currentDate.getTime() + SecurityConstants.JWT_EXPIRATION);

        SecretKey key = getSecretKey();

        return Jwts.builder()
                .subject(email)
                .issuedAt(new Date())
                .expiration(expireDate)
                .signWith(key)
                .compact();
    }

    private SecretKey getSecretKey() {
        byte[] keyBytes = Decoders.BASE64.decode(jwtSecret);
        return Keys.hmacShaKeyFor(keyBytes);
    }

    public String getEmailFromJWT(String token) {
        Claims claims = Jwts.parser()
                .verifyWith(getSecretKey())
                .build()
                .parseSignedClaims(token)
                .getPayload();
        return claims.getSubject();
    }

    public boolean validateToken(String token) {
        try {
            SecretKey key = getSecretKey();
            Jwts.parser().decryptWith(key).build().parse(token);
            return true;
        } catch(SecurityException | MalformedJwtException e) {
            throw new AuthenticationCredentialsNotFoundException("JWT was expired or incorrect");
        } catch (ExpiredJwtException e) {
            throw new AuthenticationCredentialsNotFoundException("Expired JWT token.");
        } catch (UnsupportedJwtException e) {
            throw new AuthenticationCredentialsNotFoundException("Unsupported JWT token.");
        } catch (IllegalArgumentException e) {
            throw new AuthenticationCredentialsNotFoundException("JWT token compact of handler are invalid.");
        }
    }
}

Ошибка возникает при попытке проанализировать токен в методе validateToken. Части подписи/декодирования/расшифровки/анализа мне совершенно непонятны, я понимаю, почему возникает ошибка, но понятия не имею, как ее исправить.

Извините за мой английский, это не мой родной язык.

Я пробовал несколько тем, но в основном они используют устаревшую версию jsonwebtoken. Мне бы хотелось, чтобы кто-нибудь помог мне понять, как работает часть проверки.

пожалуйста, опубликуйте полную трассировку стека в вопрос.

J Asgarov 06.08.2024 07:11

Вам не следует создавать самодельную систему безопасности по индивидуальному заказу. Прочтите документацию по безопасности Spring и выберите оттуда решение для авторизации, подходящее для вашего случая пользователя.

Toerktumlare 06.08.2024 07:47
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
2
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

проблема в том, что вы используете метод decryptWith. Этот метод предназначен только для расшифровки JWE, если вы создали его с помощью encryptWith.

Поскольку в вашей программе вы хотите использовать только JWT (не зашифрованные), вам необходимо придерживаться signWith и veryfyWith.

Поэтому измените свой метод validate на следующий:

 public boolean validateToken(String token) {
        try {
            SecretKey key = getSecretKey();
            Jwts.parser().verifyWith(key).build().parseSignedClaims(token);
            return true;
        } catch(SecurityException | MalformedJwtException e) {
            throw new AuthenticationCredentialsNotFoundException("JWT was expired or incorrect");
        } catch (ExpiredJwtException e) {
            throw new AuthenticationCredentialsNotFoundException("Expired JWT token.");
        } catch (UnsupportedJwtException e) {
            throw new AuthenticationCredentialsNotFoundException("Unsupported JWT token.");
        } catch (IllegalArgumentException e) {
            throw new AuthenticationCredentialsNotFoundException("JWT token compact of handler are invalid.");
        }
    }

Для получения дополнительной информации ознакомьтесь с документацией

Спасибо, я изменил его, но ошибка та же: io.jsonwebtoken.UnsupportedJwtException: невозможно проверить подпись JWS: невозможно найти ключ проверки подписи для JWS с заголовком: {alg=HS512}, что приводит к исключению UnsupportedJwtException в методе validateToken.

Adrien Le Gall 06.08.2024 00:07

см. мой обновленный ответ

J Asgarov 06.08.2024 07:19

Проверка теперь работает хорошо, проблема решена! Большое спасибо

Adrien Le Gall 06.08.2024 21:19

Попробуйте эти:

1. используйте постоянный ключ, как вы упомянули, может быть сгенерирован другой ключ getSecretKey();

private static final SecretKey SECRET_KEY;

2. .signWith(secretKey, io.jsonwebtoken.SignatureAlgorithm.HS512) укажите алгоритм подписи

Спасибо за ваш ответ, для 1- это уже так, а для 2- signWith(secretKey, io.jsonwebtoken.SignatureAlgorithm.HS512) не поддерживается в версии jwt, которую я использую. @Deprecated JwtBuilder signWith(Key var1, SignatureAlgorithm var2) throws InvalidKeyException; из JwtBuilder.class

Adrien Le Gall 06.08.2024 18:09

Другие вопросы по теме