Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

+1 590новых вакансий за сутки·54 897вакансий открыто сейчас·Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании5 617
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 395 кандидатов открыты к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python8 827
  • Облачные технологии6 726
  • QA вакансии2 191
  • Android1 320
  • Инженер данных862
  • Продакт-менеджер318

Разработка

  • iOS1 233
  • Backend вакансии1 214
  • AI вакансии551
  • Fullstack вакансии502
  • Frontend вакансии425
  • Mobile вакансии28

По стеку

  • Go5 252
  • Java3 137
  • Kotlin1 125
  • Node.js1 011
  • Rust852
  • .NET665
  • PHP320
  • C++270
  • C#207

DevOps и инфраструктура

  • Kubernetes3 956
  • Linux-инфраструктура2 871
  • DevOps вакансии2 690
  • Terraform / IaC2 199
  • Мониторинг и Observability1 084
  • CI/CD914
  • SRE314
  • Кибербезопасность38

Аналитика и данные

  • Аналитик данных529
  • Data Scientist437
  • Бизнес-аналитик398
  • Системный аналитик68

Другие направления

  • Проджект-менеджер109
  • UI/UX дизайн67
  • Ручное тестирование14

По регионам

  • Вакансии в США25 820
  • Вакансии в Европе10 304
  • Работа в России3 646
  • Вакансии в Канаде2 269

По формату

  • Удалённые вакансии42 570
  • Релокация в США25 820
  • Гибридная работа5 725
  • Офисная работа4 498

По уровню

  • Senior вакансии22 658
  • Middle вакансии11 501
  • Junior вакансии3 898

Сейчас нанимают

Все компании
  • Rakuten189 вакансий
  • Wise188 вакансий
  • ASML164 вакансии
  • Grab134 вакансии
  • Celonis47 вакансий
  • Spotify37 вакансий
  • Infobip28 вакансий
  • Adyen27 вакансий
  • Monzo20 вакансий
  • Darktrace17 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме Spring BootВсе вопросы
Spring BootSeniorКодинг

Как реализовать JWT-аутентификацию в Spring Boot?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Реализуется через jjwt: JwtService генерирует/валидирует токен, OncePerRequestFilter извлекает его из заголовка Authorization и выставляет SecurityContext, SecurityFilterChain добавляет фильтр перед UsernamePasswordAuthenticationFilter с STATELESS-политикой.

Зависимости

Добавьте в pom.xml (Spring Boot 3.x):

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-api</artifactId>
  <version>0.12.5</version>
</dependency>
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-impl</artifactId>
  <version>0.12.5</version>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt-jackson</artifactId>
  <version>0.12.5</version>
  <scope>runtime</scope>
</dependency>

Генерация и валидация токена

@Service
public class JwtService {
    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration-ms:3600000}")
    private long expirationMs;

    private SecretKey signingKey() {
        return Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));
    }

    public String generateToken(UserDetails user) {
        return Jwts.builder()
            .subject(user.getUsername())
            .issuedAt(new Date())
            .expiration(new Date(System.currentTimeMillis() + expirationMs))
            .signWith(signingKey())
            .compact();
    }

    public String extractUsername(String token) {
        return Jwts.parser()
            .verifyWith(signingKey())
            .build()
            .parseSignedClaims(token)
            .getPayload()
            .getSubject();
    }

    public boolean isTokenValid(String token, UserDetails user) {
        return extractUsername(token).equals(user.getUsername())
            && !isExpired(token);
    }

    private boolean isExpired(String token) {
        return Jwts.parser()
            .verifyWith(signingKey())
            .build()
            .parseSignedClaims(token)
            .getPayload()
            .getExpiration()
            .before(new Date());
    }
}

OncePerRequestFilter

@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
    private final JwtService jwtService;
    private final UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest req,
                                    HttpServletResponse res,
                                    FilterChain chain)
            throws ServletException, IOException {
        String header = req.getHeader(HttpHeaders.AUTHORIZATION);
        if (header == null || !header.startsWith("Bearer ")) {
            chain.doFilter(req, res);
            return;
        }
        String token = header.substring(7);
        String username = jwtService.extractUsername(token);
        if (username != null
                && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails user = userDetailsService.loadUserByUsername(username);
            if (jwtService.isTokenValid(token, user)) {
                var auth = new UsernamePasswordAuthenticationToken(
                    user, null, user.getAuthorities());
                auth.setDetails(new WebAuthenticationDetailsSource()
                    .buildDetails(req));
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
        }
        chain.doFilter(req, res);
    }
}

SecurityFilterChain

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    private final JwtAuthFilter jwtAuthFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(AbstractHttpConfigurer::disable)
            .sessionManagement(s ->
                s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated()
            )
            .addFilterBefore(jwtAuthFilter,
                UsernamePasswordAuthenticationFilter.class)
            .build();
    }

    @Bean
    public AuthenticationManager authManager(
            AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Подводные камни

  • Хранить jwt.secret в application.properties в репозитории нельзя — используйте env-переменные или Vault.
  • Алгоритм HS256 с коротким секретом уязвим к брутфорсу; рекомендуется RS256 (пара ключей) в production.
  • JWT без revocation: при logout или смене пароля старый токен остаётся валидным до exp — нужен blocklist в Redis.
  • SecurityContextHolder использует ThreadLocal — в реактивном стеке (WebFlux) нужен ReactiveSecurityContextHolder.
  • Не проверять exp вручную: jjwt выбрасывает ExpiredJwtException при парсинге — достаточно поймать его в фильтре.
  • Access-токен должен быть коротким (15–60 мин); refresh-токен — длинным (7–30 дней), хранить в httpOnly cookie.
  • Не передавать sensitive данные (пароль, номер карты) в payload — JWT только base64-encoded, не зашифрован.

Частые вопросы на собеседовании

  • Как реализовать health checks в Spring Boot Actuator?
  • Что делает аннотация @SpringBootApplication?
  • Что такое Spring Boot и чем он отличается от Spring Framework?
  • В каких backend-проектах Spring Boot является сильным выбором, а где лучше выбрать более простой или другой стек?

Типичные ошибки

  • Путать термин «jwt authentication» с соседним механизмом Spring Boot.
  • Не называть границу lifecycle, transaction, thread или request для «jwt authentication».
  • Игнорировать production-эффекты «jwt authentication»: latency, SQL shape, memory, security или observability.

Что проверяет интервьюер

  • Попросить объяснить механизм «jwt authentication» на минимальном примере.
  • Проверить, видит ли кандидат failure mode и диагностику для «jwt authentication».
  • Уточнить, какие настройки или API меняют «jwt authentication» в реальном сервисе.

Как вы знаете этот вопрос?

Проверить себя по теме Spring Boot →

Источники

  • https://docs.spring.io/spring-boot/reference/web/spring-security.html
←Предыдущий вопросЧто такое `@Transactional` и каковы его уровни propagation и isolation?Следующий вопрос→Какие production-риски есть у Spring Boot: blocking code, connection pooling, config, auth, observability, deploy или graceful shutdown?

Связанные темы

Spring Bootapi-securityimplementationthreat-modeling

Вакансии с этим навыком

  • Backend-разработчик (Java/Kotlin)
  • IT Specialists: Cybersecurity, CPO, Java Backend Developer
  • Senior Software Engineer
  • Senior Java-разработчик
  • Ведущий Java-разработчик МСБ