Авторизация и аутентификация в Java: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Авторизация и аутентификация в Java: основные концепции и инструменты

Аутентификация и авторизация — два фундаментальных столпа безопасности любого веб-приложения. В экосистеме Java для этих задач существует множество зрелых библиотек и фреймворков. В данной статье мы подробно разберём ключевые инструменты, их особенности и приведём практические примеры кода.

1. Основные понятия

Прежде чем перейти к инструментам, важно чётко разделить термины:

  • Аутентификация — проверка подлинности пользователя (кто вы?). Обычно выполняется через логин/пароль, токены или биометрию.
  • Авторизация — проверка прав доступа (что вам разрешено?). Определяет, может ли пользователь выполнять определённые действия.

2. Spring Security — стандарт де-факто

Spring Security — самый популярный фреймворк для обеспечения безопасности в Java-приложениях. Он предоставляет комплексное решение как для аутентификации, так и для авторизации.

2.1. Базовая настройка аутентификации

Для подключения Spring Security добавьте зависимость в pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Минимальная конфигурация с in-memory аутентификацией:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    @Bean
    public InMemoryUserDetailsManager userDetailsManager() {
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authz -> authz
                        .requestMatchers("/admin/**").hasRole("ADMIN")
                        .requestMatchers("/user/**").hasRole("USER")
                        .anyRequest().authenticated()
                )
                .formLogin(login -> login.defaultSuccessUrl("/home"))
                .httpBasic();
        return http.build();
    }
}

3. JWT (JSON Web Tokens) для stateless-аутентификации

JWT позволяет реализовать аутентификацию без сохранения состояния на сервере. Токен содержит всю необходимую информацию о пользователе и подписывается секретным ключом.

3.1. Генерация JWT с помощью библиотеки jjwt

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

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.12.5</version>
</dependency>

Пример создания и проверки токена:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;

public class JwtUtil {

    private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    private static final long EXPIRATION_TIME = 3600000; // 1 час

    public static String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SECRET_KEY)
                .compact();
    }

    public static String extractUsername(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }

    public static boolean validateToken(String token) {
        try {
            Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

4. BCrypt — безопасное хранение паролей

Никогда не храните пароли в открытом виде! BCrypt — адаптивный алгоритм хеширования, устойчивый к атакам перебором.

Использование с Spring Security:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class PasswordEncoderDemo {
    public static void main(String[] args) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

        String rawPassword = "mySecret123";
        String encodedPassword = encoder.encode(rawPassword);

        System.out.println("Захешированный пароль: " + encodedPassword);

        // Проверка пароля
        boolean matches = encoder.matches("mySecret123", encodedPassword);
        System.out.println("Пароль совпадает: " + matches); // true
    }
}

5. OAuth2 и OpenID Connect

Для интеграции с внешними провайдерами (Google, GitHub, Facebook) используется протокол OAuth

Рекомендаций