Лучшие практики для JWT в Spring Boot: построение непроницаемой крепости безопасности
Лучшие практики для JWT в Spring Boot: построение непроницаемой крепости безопасности

Предисловие

Привет всем, я из сообщества разработчиков Tencent Cloud. Front_Yue,В этой статье мы расскажем, что такое JWT и как его использовать в JWT.

В современных веб-приложениях безопасность имеет решающее значение. Для аутентификации пользователей и защиты данных приложений мы обычно используем механизмы аутентификации и авторизации. JSON Web Token (JWT) — это открытый стандарт (RFC 7519), определяющий компактный, автономный способ безопасной передачи информации между сторонами в виде объекта JSON. Эти сообщения можно проверить и им можно доверять, поскольку они имеют цифровую подпись. JWT можно подписать с использованием алгоритма HMAC или пары открытого/закрытого ключей RSA или ECDSA.

В приложениях Spring Boot JWT часто используется как метод аутентификации без сохранения состояния, позволяющий клиенту использовать JWT при каждом запросе аутентификации.

Текстовый контент

1. Структура JWT

JWT обычно состоит из трех частей,использовать между ними.отдельный,следующее:

Язык кода:java
копировать
xxxxx.yyyyy.zzzzz
1. Заголовок

Обычно содержит две части информации:

  • Тип токена, в данном случае JWT.
  • Используемый алгоритм подписи, например HMAC SHA256 или RSA.

Например:

Язык кода:json
копировать
{
  "alg": "HS256",
  "typ": "JWT"
}

Этот объект JSON закодирован Base64Url и образует первую часть JWT.

2. Полезная нагрузка

Содержит заявление. Утверждения — это утверждения об объектах (обычно пользователях) и других данных. Существует три типа претензий: зарегистрированные претензии, публичные претензии и частные претензии.

Например:

Язык кода:json
копировать
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

Этот объект JSON также закодирован Base64Url и образует вторую часть JWT.

3. Подпись

Это подпись двух вышеупомянутых частей контента, предотвращающая подделку контента.

Эта часть является сигнатурой первых двух частей и требует указания секрета. Этот ключ известен только серверу и должен храниться в секрете. Сервер использует этот ключ для подписи заголовка и полезных данных при создании токена и генерирует третью часть. Клиент приносит этот JWT со своим запросом, а сервер использует тот же ключ для проверки.

2. Использование JWT в Spring Boot

В Spring Boot вы можете интегрировать JWT, выполнив следующие действия:

1. Добавьте зависимости

первый,существоватьpom.xmlДобавитьJWTсвязанные зависимости,нравитьсяjjwt

Язык кода:xml
копировать
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
2. Создайте класс инструмента JWT.

Нам нужно создать в проекте класс инструмента Java для генерации и проверки JWT:

Язык кода:java
копировать
public class JwtUtils {

    private static final String SECRET = "your_secret_key"; // ключ
    private static final long JWT_EXPIRATION = 604800000; // Срок действия одна неделя
    // Создать токен JWT
    public static String generateToken(String username) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + JWT_EXPIRATION);

        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(now)
                .setExpiration(expiryDate)
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }
    // Проверьте токен JWT
    public static Claims validateToken(String token) {
        try {
            return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        } catch (ExpiredJwtException e) {
            // Срок действия JWT истекает
            e.printStackTrace();
        } catch (UnsupportedJwtException e) {
            // Неподдерживаемый JWT
            e.printStackTrace();
        } catch (MalformedJwtException e) {
            // Ошибка формата JWT
            e.printStackTrace();
        } catch (SignatureException e) {
            // Подпись JWT несовместима
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // JWT пуст или имеет неверный формат.
            e.printStackTrace();
        }
        return null;
    }
}
3. Создайте фильтры аутентификации.

В проекте нам необходимо создать фильтр для перехвата запросов, отправленных клиентом, а серверу необходимо проверить корректность парсинга JWT.

Язык кода:java
копировать
@Component
public class JwtAuthenticationFilter extends Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // Операция инициализации, опционально
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String tokenHeader = httpRequest.getHeader("Authorization");

        if (tokenHeader == null || !tokenHeader.startsWith("Bearer ")) {
            chain.doFilter(request, response);
            return;
        }

        // Получите токен и подтвердите
        String token = tokenHeader.substring(7);
        Claims claims = JwtUtils.validateToken(token);

        if (claims == null) {
            // Проверка не удалась, обработка ситуаций без аутентификации
            // Например: Возвращает 401 Неавторизованный код статуса.
        } else {
            // Проверка прошла успешно, установите данные для аутентификации пользователя.
            UserDetails userDetails = // Получите UserDetails на основе информации в заявках.
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // Операция уничтожения, опционально
    }
}

В приведенном выше коде,Мы создалиJwtAuthenticationFilter,Он будет запускаться перед каждым запросом,Проверьте, содержит ли заголовок запроса клиента действительный JWT. если содержит,Он извлечет информацию о пользователе из JWT.,и использоватьSecurityContextHolderЧтобы установить текущего аутентифицированного пользователя。

4. Создайте интерфейс входа пользователя.

когда пользователь входит в систему,Можно использоватьJwtUtilsгенерироватьJWT,и вернуть его клиенту. Клиент должен сохранить этот JWT локально.,Убедитесь, что вы настроили логику генерации и проверки JWT.,включая созданиеJWTКласс инструмента(JwtUtils)и для хранения и проверкиJWTинформационныйключ,Ниже приведен пример интерфейса входа в систему, который я создал.,Только для справки.

Язык кода:java
копировать
@Api(tags = «Управление списком пользователей»)
@RestController
public class SysUserController extends BaseController {
    @ApiOperation("Вход по учетной записи и паролю")
    @GetMapping("/login")
    public AjaxResult login(@RequestParam String userName, @RequestParam String password) {
        if (userName != null && password != null) {
            SysUser sysUser = new SysUser();
            sysUser.setUserName(userName);
            sysUser.setPassword(newPassword);
            List<SysUser> user = sysUserService.list(sysUser);
            if (user.size() == 1) {
                return success(setUserInfo(user.get(0)));
            } else {
                return error("Имя пользователя или пароль неверны");
            }
        } else {
            return error("Имя пользователя или пароль не могут быть пустыми");
        }
    }


    public Map<String, Object> setUserInfo(SysUser userInfo) {
        String jwt = JwtUtil.createToken(userInfo.getUserId(), userInfo.getUserName(), userInfo.getOpenid()); //jwt содержит информацию о вошедшем в систему сотруднике
        loginInfo.setUserId(userInfo.getUserId());
        Map<String, Object> map = new HashMap<>();
        map.put("userinfo", userInfo);
        map.put("token", jwt);
        return map;
    }
}

3. Клиентское хранение и использование JWT

После того, как клиент (например, интерфейсное приложение) успешно войдет в систему,,После получения JWT,должен Воляего сохранениесуществоватьlocalStoragesessionStorageилиcookiesсередина。существоватьпоследующие запросысередина,Клиент должен пройтиHTTPЗаголовок запроса(нравитьсяAuthorization)ВоляJWTОтправлено на сервер для проверки。

1. Сохраните токен JWT
Язык кода:js
копировать
const handleLogin = async () => {
  if (user.validCode == validCode.value) {
    const res: any = await login(user);
    if (res.code == 200) {
      sessionStorage.setItem("token", res.data.token);
      store.setUserInfo(res.data.userinfo);
    }
  }
}  
2. Используйте токены JWT
Язык кода:js
копировать
// перехватчик запросов
service.interceptors.request.use(config => {
    // Перед отправкой каждого запроса определите, есть ли токен в vuex.        
    // Если он существует, токен будет добавлен в заголовок HTTP-запроса, чтобы фон определял ваш статус входа на основе токена.
    // Даже если токен существует локально, возможно, срок действия токена истек, поэтому статус возврата должен оцениваться в перехватчике ответа. 
    config.headers['Authorization'] = 'Bearer ' + sessionStorage.getItem('token');
    return config;
}, error => {
    Promise.reject(error);
})

4. Обновить токен

Чтобы повысить безопасность, вы можете рассмотреть возможность реализации механизма токена обновления. Долгосрочные токены (токены доступа) обычно имеют более короткий срок действия, тогда как токены обновления (токены обновления) имеют более длительный срок действия. По истечении срока действия токена доступа клиент может использовать токен обновления для получения нового токена доступа, не требуя от пользователя повторного входа в систему.

5. Обработка истечения срока действия JWT

Когда срок действия токена JWT клиента истечет, запросы, которые мы отправляем через клиент, будут отклонены. Вам необходимо разработать механизм для обработки этой ситуации, например, предложить пользователю снова войти в систему или автоматически использовать токен обновления для получения нового токена доступа.

Подвести итог

Использование JWT для аутентификации и авторизации пользователей обеспечивает гибкость и масштабируемость, упрощая управление сеансами пользователей приложениям с отдельными внешними и внутренними компонентами. Правильно настроив класс инструмента JWT, мы можем легко реализовать аутентификацию JWT в приложениях Spring Boot. Убедитесь, что ваши ключи JWT хранятся надежно и часто заменяются, чтобы предотвратить потенциальные угрозы безопасности.

Наконец, я хотел бы поблагодарить моих друзей из сообщества разработчиков Tencent Cloud за их сотрудничество. Если вам нравится контент моего блога и вы цените мои взгляды и обмен опытом, ставьте лайки, собирайте и комментируйте. Это будет моей самой большой поддержкой и поощрением. В то же время я также приветствую ценные комментарии и предложения каждого, чтобы я мог лучше улучшить и усовершенствовать свой блог. Спасибо!

Я участвую в последнем конкурсе эссе для специального учебного лагеря Tencent Technology Creation 2024. Приходите и разделите со мной приз!

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose