← Назад к вопросам
В чем разница между JWT и сессией?
2.2 Middle🔥 271 комментариев
#REST API и микросервисы#Безопасность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# JWT vs Сессия: Полное Сравнение
JWT (JSON Web Token) и сессия — два основных подхода к аутентификации в веб-приложениях. Каждый имеет свои преимущества и недостатки.
Что такое сессия
Механизм работы
Сессия — это сохраненное на сервере состояние пользователя. Процесс:
- Пользователь логинится с паролем
- Сервер создает сессию (уникальный ID) и сохраняет её в памяти/БД
- Сервер отправляет cookie с session ID клиенту
- Клиент автоматически отправляет cookie при каждом запросе
- Сервер ищет сессию по ID и проверяет её существование
Пример на Spring Security
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
Authentication auth = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getUsername(),
request.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(auth);
// Spring автоматически создает сессию
return ResponseEntity.ok("Logged in");
}
@GetMapping("/profile")
public ResponseEntity<?> getProfile() {
// Spring проверяет сессию автоматически
User user = (User) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
return ResponseEntity.ok(user);
}
Что такое JWT
Механизм работы
JWT — это зашифрованный самодостаточный токен. Процесс:
- Пользователь логинится с паролем
- Сервер создает JWT (подписанный токен с данными пользователя)
- Сервер отправляет JWT клиенту
- Клиент сохраняет в localStorage/sessionStorage и отправляет в заголовке Authorization
- Сервер проверяет подпись JWT без обращения к БД
Пример на Spring Security + JWT
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
Authentication auth = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getUsername(),
request.getPassword()
)
);
String token = jwtProvider.generateToken(auth);
return ResponseEntity.ok(new JwtResponse(token));
}
@GetMapping("/profile")
public ResponseEntity<?> getProfile(
@RequestHeader("Authorization") String authHeader) {
String token = authHeader.substring(7); // Remove "Bearer "
if (jwtProvider.validateToken(token)) {
String username = jwtProvider.getUsername(token);
User user = userService.findByUsername(username);
return ResponseEntity.ok(user);
}
return ResponseEntity.status(401).build();
}
Структура JWT
JWT состоит из трех частей, разделенных точками: header.payload.signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Header (Заголовок)
{
"alg": "HS256",
"typ": "JWT"
}
Payload (Данные)
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}
Signature (Подпись)
HMAC_SHA256(
base64url(header) + "." + base64url(payload),
secret_key
)
Сравнительная таблица
| Критерий | Сессия | JWT |
|---|---|---|
| Хранилище | На сервере (Memory, DB) | На клиенте |
| Масштабируемость | Сложно (нужна общая БД) | Легко (stateless) |
| Безопасность | Сильнее (хранится на сервере) | Требует HTTPS |
| Размер данных | Маленький (только ID) | Больше (содержит данные) |
| Logout | Простой (удалить сессию) | Сложный (чёрный список токенов) |
| CSRF | Уязвима | Защищена (токен не в cookie) |
| Мобильные приложения | Сложно | Отлично подходит |
| API и микросервисы | Требует общего хранилища | Идеально подходит |
Практические примеры
Сессия: Монолитное приложение
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.and()
.sessionManagement()
.sessionFixationProtection(SessionFixationProtection.MIGRATE_SESSION)
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
return http.build();
}
}
JWT: Микросервисы и API
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.requestMatchers("/api/auth/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Когда что использовать
Используй Сессию когда:
- Монолитное веб-приложение
- Классический MVC (JSP, Thymeleaf)
- Высокие требования к безопасности
- Нужен простой logout
- Использование cookies приемлемо
Используй JWT когда:
- SPA (Single Page Application) на React/Vue
- Микросервисная архитектура
- Мобильное приложение (iOS/Android)
- REST API
- Кросс-доменные запросы (CORS)
- Stateless масштабирование нужно
Гибридный подход
Многие приложения используют оба подхода:
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
// Проверяем пароль
Authentication auth = authenticationManager.authenticate(...);
// Создаем JWT для фронта
String jwtToken = jwtProvider.generateToken(auth);
// Создаем сессию для безопасности
SecurityContextHolder.getContext().setAuthentication(auth);
return ResponseEntity.ok(new LoginResponse(jwtToken));
}
Безопасность
JWT требует:
- Использование HTTPS (никогда HTTP)
- Хранение в httpOnly cookie или защищенном localStorage
- Короткий срок действия (access token: 15 минут)
- Refresh token для обновления
- Защита от XSS атак
Сессия требует:
- httpOnly и Secure флаги на cookie
- CSRF токен в POST запросах
- Регулярная ротация session ID
- Защита от session fixation атак
Заключение
В современной Java разработке часто комбинируют оба подхода: JWT для API и микросервисов, сессии для веб-приложений. Выбор зависит от архитектуры приложения, требований к масштабируемости и типа клиентов.