JWT для програмістів: що це таке і як правильно використовувати

Якщо ви програміст і працюєте з веб-додатками, то напевно чули про JWT (JSON Web Token). Але багато розробників досі не розуміють, що це насправді таке і коли його варто використовувати. Можливо, ви навіть намагалися його впровадити, але зіткнулися з питаннями: чому JWT краще сесій? Коли його НЕ варто використовувати? Як зробити це безпечно? У цій статті ми розберемо JWT простою мовою, з реальними прикладами і практичними рекомендаціями.

Що таке JWT простими словами

Уявіте, що ви йдете в клуб. На вході вам дають браслет з печаткою, який підтверджує, що ви заплатили за вхід. Цей браслет містить інформацію про вас (ім'я, вік) і печатку клубу, яку неможливо підробити. З цим браслетом ви можете ходити по всьому клубу, заходити в VIP-зону, якщо у вас є відповідний статус, і вам не потрібно щоразу підходити до каси і доводити, що ви заплатили.

JWT працює аналогічно — це цифровий "браслет", який містить інформацію про користувача і захищений цифровим підписом. Сервер видає цей токен після успішної авторизації, і клієнт використовує його для доступу до захищених ресурсів.

JWT складається з трьох частин, розділених крапками:

• Header — містить інформацію про тип токена і алгоритм підпису

• Payload — містить дані про користувача (ID, ролі, права доступу)

• Signature — цифровий підпис, який гарантує, що токен не був змінений

Виглядає це приблизно так: `xxxxx.yyyyy.zzzzz`

Реальні проблеми, які вирішує JWT

Проблема #1: Масштабування додатка

Уявіте інтернет-магазин з мільйонами користувачів. При традиційному підході з сесіями, сервер повинен зберігати інформацію про кожну активну сесію в пам'яті або базі даних. Коли у вас 100,000 одночасних користувачів, це стає серйозною проблемою.

👉 Приклад:

• Кожна сесія займає ~1KB пам'яті

• 100,000 користувачів = 100MB тільки на сесії

• Плюс час на запити до бази для перевірки кожної сесії

JWT вирішує цю проблему, бо вся необхідна інформація зберігається в самому токені. Сервер не повинен нічого зберігати — він просто перевіряє підпис токена і отримує всю необхідну інформацію.

Проблема #2: Робота з мікросервісами

Сучасні додатки часто складаються з декількох сервісів. Наприклад, у вас є сервіс користувачів, сервіс товарів, сервіс платежів. З традиційними сесіями кожен сервіс повинен звертатися до центральної бази даних, щоб перевірити, чи авторизований користувач.

⚡ Наприклад: користувач хоче купити товар. Йому потрібно пройти через 4 сервіси, і кожен з них робить запит до бази користувачів. Це 4 додаткових запити!

З JWT кожен сервіс може самостійно перевірити токен, не звертаючись до інших сервісів. Це значно спрощує архітектуру і підвищує продуктивність.

Проблема #3: Мобільні додатки і API

Мобільні додатки не підтримують cookies так само добре, як браузери. JWT ідеально підходить для мобільних додатків, бо це просто рядок, який можна зберегти в локальній пам'яті додатка.

Крок за кроком: як працює JWT

Крок 1. Користувач логіниться

Користувач вводить email і пароль. Сервер перевіряє ці дані у базі.

👉 Приклад коду на Java:

```java

@PostMapping("/login")

public ResponseEntity login(@RequestBody LoginRequest request) {

User user = userService.authenticate(request.getEmail(), request.getPassword());

if (user != null) {

String token = createToken(user);

return ResponseEntity.ok(token);

}

return ResponseEntity.status(401).body("Invalid credentials");

}

```

Крок 2. Сервер створює JWT токен

Якщо дані правильні, сервер створює токен з інформацією про користувача:

```java

public String createToken(User user) {

return Jwts.builder()

.setSubject(user.getEmail())

.claim("userId", user.getId())

.claim("role", user.getRole())

.setIssuedAt(new Date())

.setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 24 години

.signWith(SignatureAlgorithm.HS256, secretKey)

.compact();

}

```

Крок 3. Клієнт зберігає токен

Клієнт отримує токен і зберігає його (зазвичай в localStorage або у змінній додатка).

Крок 4. Клієнт використовує токен

При кожному запиті до захищених ресурсів клієнт відправляє токен в заголовку Authorization:

```

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

```

Крок 5. Сервер перевіряє токен

Сервер перевіряє підпис токена і витягує з нього інформацію про користувача:

```java

public Claims validateToken(String token) {

return Jwts.parser()

.setSigningKey(secretKey)

.parseClaimsJws(token)

.getBody();

}

```

Реальні приклади використання

Приклад 1: Інтернет-магазин електроніки

Розглянемо типовий сценарій в інтернет-магазині:

• Користувач логіниться

• Додає товари в кошик

• Переходить до оформлення замовлення

• Робить платіж

Кожна з цих дій потребує авторизації. З JWT ви можете включити в токен:

```java

public String createShopToken(User user) {

return Jwts.builder()

.setSubject(user.getEmail())

.claim("userId", user.getId())

.claim("role", user.getRole()) // "customer", "admin", "manager"

.claim("cartId", user.getCurrentCartId())

.claim("loyaltyLevel", user.getLoyaltyLevel()) // для знижок

.setIssuedAt(new Date())

.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 година

.signWith(SignatureAlgorithm.HS256, secretKey)

.compact();

}

```

⚡ Переваги: сервіс кошика може самостійно перевірити, чи належить кошик користувачу, без запитів до бази користувачів.

Приклад 2: API для соціальної мережі

Уявіте, що ви розробляєте API для соціальної мережі на кшталт Instagram. Користувачі можуть:

• Переглядати стрічку новин

• Публікувати фото

• Коментувати пости

• Відправляти особисті повідомлення

👉 Приклад токена для соціальної мережі:

```java

public String createSocialToken(User user) {

return Jwts.builder()

.setSubject(user.getUsername())

.claim("userId", user.getId())

.claim("role", user.getRole())

.claim("verified", user.isVerified()) // верифікований акаунт

.claim("permissions", user.getPermissions()) // що може робити

.claim("followersCount", user.getFollowersCount()) // для рекомендацій

.setIssuedAt(new Date())

.setExpiration(new Date(System.currentTimeMillis() + 1800000)) // 30 хвилин

.signWith(SignatureAlgorithm.HS256, secretKey)

.compact();

}

```

JWT vs інші методи аутентифікації

Порівняння з традиційними сесіями

**Традиційні сесії:**

👍 Плюси:

• Сервер має повний контроль над сесією

• Можна миттєво відкликати доступ

• Менший розмір cookies (тільки session ID)

• Більш захищені від XSS атак

👎 Мінуси:

• Потребують зберігання на сервері

• Складніше масштабувати

• Проблеми з мікросервісами

• Не підходять для мобільних додатків

**JWT:**

👍 Плюси:

• Не потребує зберігання на сервері

• Легко масштабується

• Ідеально для мікросервісів

• Підходить для мобільних додатків

• Містить всю необхідну інформацію

👎 Мінуси:

• Неможливо миттєво відкликати

• Більший розмір

• Складніше оновлювати дані користувача

• Потенційно менш захищені

Порівняння з OAuth

OAuth — це не альтернатива JWT, а протокол авторизації, який часто використовує JWT як формат токенів. OAuth вирішує проблему надання доступу третім сторонам (наприклад, коли ви логінитесь через Google або Facebook).

Коли використовувати JWT

Ідеальні сценарії:

• **Мікросервісна архітектура** — коли у вас багато незалежних сервісів

• **API для мобільних додатків** — JWT легко зберігати і передавати

• **Одноразова авторизація** — коли користувач рідко змінює свої дані

• **Розподілені системи** — коли сервери не поділяють спільну базу даних

• **Короткострокові токени** — для сесій тривалістю до кількох годин

Коли краще НЕ використовувати JWT:

• **Довготривалі сесії** — для сесій, що тривають днями або тижнями

• **Часті зміни даних користувача** — коли ролі і права часто оновлюються

• **Строгі вимоги безпеки** — коли потрібна можливість миттєво відкликати доступ

• **Обмежена пропускна здатність** — JWT токени більші за session ID

⚠️ Важливо: якщо ви сумніваєтесь, почніть з традиційних сесій. Їх легше налаштувати і вони безпечніші за замовчуванням.

Найкращі практики безпеки

1. Завжди використовуйте HTTPS

JWT токени містять чутливу інформацію в незашифрованому вигляді. Завжди передавайте їх через HTTPS.

2. Встановлюйте короткий термін дії

Рекомендується встановлювати термін дії токена 15-60 хвилин для звичайних операцій.

👉 Приклад:

```java

.setExpiration(new Date(System.currentTimeMillis() + 900000)) // 15 хвилин

```

3. Використовуйте Refresh токени

Для довготривалого доступу використовуйте систему з двома токенами: коротким access токеном і довшим refresh токеном.

4. Зберігайте токени безпечно

У браузері краще зберігати токени в httpOnly cookies, а не в localStorage, щоб захистити від XSS атак.

5. Валідуйте всі поля

Завжди перевіряйте не тільки підпис токена, а й термін дії, аудиторію та інші claims:

```java

public boolean isTokenValid(String token) {

try {

Claims claims = Jwts.parser()

.setSigningKey(secretKey)

.parseClaimsJws(token)

.getBody();

// Перевірка терміну дії

return !claims.getExpiration().before(new Date());

} catch (Exception e) {

return false;

}

}

```

Що це означає для розробника

1. JWT не магія. Це лише інструмент, який спрощує роботу з авторизацією, але не замінює якісну архітектуру та безпеку.

2. Не всі проекти потребують JWT. Для простих веб-додатків традиційні сесії можуть бути кращим вибором.

3. Безпека — це не про JWT vs сесії. Це про правильну реалізацію, HTTPS, валідацію та захист від атак.

4. Масштабування важливе, але не завжди. Якщо у вас 1000 користувачів, проблеми масштабування вас не торкнуться найближчі роки.

Висновок

JWT — це потужний інструмент для сучасної веб-розробки, але він не є універсальним рішенням. Вибір між JWT і традиційними сесіями залежить від ваших конкретних потреб: для мікросервісів і API JWT ідеальний варіант, для традиційних веб-додатків сесії можуть бути кращим вибором, для мобільних додатків JWT практично незамінний.

Головне — розуміти переваги і недоліки кожного підходу і вибирати найкращий інструмент для вашої конкретної задачі. JWT не зробить ваш додаток автоматично кращим, але при правильному використанні може значно спростити архітектуру і підвищити продуктивність.

Пам'ятайте: безпека завжди повинна бути пріоритетом. Незалежно від того, який метод аутентифікації ви обираєте, завжди дотримуйтесь найкращих практик безпеки і регулярно оновлюйте свої знання в цій сфері.