← Назад к вопросам

Что такое JWT авторизация?

1.0 Junior🔥 91 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

JWT авторизация

JWT (JSON Web Token) — это способ передачи информации между сторонами в виде JSON объекта, подписанного цифровой подписью. Это современный стандарт для аутентификации и авторизации в REST API и микросервисах.

Структура JWT

JWT состоит из трёх частей, разделённых точками: header.payload.signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header (заголовок) — описывает алгоритм и тип токена:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload (полезная нагрузка) — содержит claims (утверждения):

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}

Signature (подпись) — обеспечивает целостность токена:

HMAC-SHA256(base64(header) + "." + base64(payload), secret_key)

Как работает JWT авторизация

  1. Аутентификация: Пользователь отправляет логин/пароль
  2. Создание токена: Сервер проверяет credentials и генерирует JWT
  3. Отправка клиенту: Клиент сохраняет токен (localStorage, sessionStorage или cookie)
  4. Использование токена: Клиент отправляет токен в заголовке: Authorization: Bearer <token>
  5. Проверка на сервере: Сервер верифицирует подпись и проверяет expiration

Реализация с Spring Security

@Configuration
@EnableWebSecurity
public class JwtSecurityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated()
            .and()
            .addFilterBefore(
                new JwtAuthenticationFilter(),
                UsernamePasswordAuthenticationFilter.class
            )
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        
        return http.build();
    }
}

Генерация JWT токена

@Service
public class JwtTokenProvider {
    
    @Value("${jwt.secret}")
    private String jwtSecret;
    
    @Value("${jwt.expiration}")
    private long jwtExpirationMs;
    
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("roles", userDetails.getAuthorities());
        
        return createToken(claims, userDetails.getUsername());
    }
    
    private String createToken(Map<String, Object> claims, String subject) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + jwtExpirationMs);
        
        return Jwts.builder()
            .setClaims(claims)
            .setSubject(subject)
            .setIssuedAt(now)
            .setExpiration(expiryDate)
            .signWith(SignatureAlgorithm.HS512, jwtSecret)
            .compact();
    }
    
    public String getUsernameFromToken(String token) {
        return Jwts.parser()
            .setSigningKey(jwtSecret)
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    }
    
    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }
}

Фильтр для обработки JWT

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    @Autowired
    private JwtTokenProvider tokenProvider;
    
    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        
        try {
            String jwt = extractTokenFromRequest(request);
            
            if (jwt != null && tokenProvider.validateToken(jwt)) {
                String username = tokenProvider.getUsernameFromToken(jwt);
                
                // Создаём Authentication объект
                Authentication auth = new UsernamePasswordAuthenticationToken(
                    username, null, new ArrayList<>()
                );
                
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
        } catch (Exception e) {
            logger.error("Cannot set user authentication", e);
        }
        
        filterChain.doFilter(request, response);
    }
    
    private String extractTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

Контроллер для login

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    
    @Autowired
    private JwtTokenProvider tokenProvider;
    
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        // Проверяем credentials (в реальной системе через AuthenticationManager)
        String token = tokenProvider.generateToken(
            new User(loginRequest.getUsername(), "")
        );
        
        return ResponseEntity.ok(
            new JwtAuthResponse(token, "Bearer", jwtExpirationMs / 1000)
        );
    }
}

class JwtAuthResponse {
    public String accessToken;
    public String tokenType = "Bearer";
    public long expiresIn;
    
    public JwtAuthResponse(String accessToken, String tokenType, long expiresIn) {
        this.accessToken = accessToken;
        this.tokenType = tokenType;
        this.expiresIn = expiresIn;
    }
}

Преимущества JWT

  • Stateless: Сервер не хранит сессии, легче масштабировать
  • Мобильный friendly: Хорошо работает с мобильными приложениями
  • Cross-domain: Можно использовать в CORS сценариях
  • Самодостаточный: Содержит всю необходимую информацию
  • Безопасный: Подписан и может быть зашифрован

Недостатки JWT

  • Невозможно отозвать: Токен действителен до истечения (нужна чёрный список)
  • Размер: Больше, чем обычная сессия ID
  • Утечка данных: Payload кодируется, но не шифруется

Лучшие практики

  • Используй HTTPS для всех коммуникаций
  • Храни токен в secure cookies или sessionStorage (не localStorage)
  • Реализуй refresh token для обновления доступа
  • Устанавливай короткое время expiration (15-30 минут)
  • Добавь чёрный список для отозванных токенов при необходимости
Что такое JWT авторизация? | PrepBro