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

Какие знаешь способы авторизации?

2.2 Middle🔥 221 комментариев
#REST API и микросервисы#Spring Framework#Безопасность

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

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

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

Способы авторизации в современных веб-приложениях

Авторизация — это проверка прав доступа пользователя к ресурсам. Рассмотрим наиболее распространённые механизмы, используемые в Java экосистеме.

HTTP Basic Authentication

Basic Auth — простейший способ, основанный на кодировании учетных данных в заголовок Authorization:

@Configuration
@EnableWebSecurity
public class BasicAuthSecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults());
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.builder()
            .username("john")
            .password("{bcrypt}$2a$10$...") // bcrypt хеш пароля
            .roles("USER")
            .build();

        UserDetails admin = User.builder()
            .username("admin")
            .password("{bcrypt}$2a$10$...")
            .roles("ADMIN")
            .build();

        return new InMemoryUserDetailsManager(user, admin);
    }
}

Клиентское использование:

curl -u john:password123 http://localhost:8080/api/users

Преимущества: простота, встроенная поддержка Недостатки: учетные данные в каждом запросе (требует HTTPS), сложно выходить

Form-Based Authentication (Session)

Session-based auth — традиционный способ с использованием cookies:

@Configuration
@EnableWebSecurity
public class SessionAuthSecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/login", "/register").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .defaultSuccessUrl("/home")
                .permitAll()
            )
            .logout(logout -> logout
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login")
            )
            .sessionManagement(session -> session
                .sessionFixationProtection(SessionFixationProtection.MITIGATE)
                .sessionConcurrency(concurrency -> concurrency
                    .maximumSessions(1)
                    .expiredUrl("/login")
                )
            );
        return http.build();
    }
}

@Controller
public class LoginController {
    @PostMapping("/login")
    public String login(@RequestParam String username, 
                       @RequestParam String password,
                       HttpSession session) {
        // Валидация учетных данных
        if (validateCredentials(username, password)) {
            session.setAttribute("user", username);
            return "redirect:/home";
        }
        return "redirect:/login?error";
    }
}

Преимущества: безопасна, встроенная поддержка, простой logout Недостатки: требует хранения session на сервере, масштабируется плохо

JWT (JSON Web Token)

JWT — самоконтайнeрный способ без хранения состояния на сервере:

@Configuration
@EnableWebSecurity
public class JwtSecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/login").permitAll()
                .anyRequest().authenticated()
            )
            .addFilterBefore(jwtAuthenticationFilter(), 
                UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter();
    }
}

@Component
public class JwtTokenProvider {
    @Value("${jwt.secret}")
    private String secretKey;

    @Value("${jwt.expiration}")
    private long expirationTime; // ms

    public String generateToken(String username, List<String> roles) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + expirationTime);

        return Jwts.builder()
            .setSubject(username)
            .claim("roles", roles)
            .setIssuedAt(now)
            .setExpiration(expiryDate)
            .signWith(SignatureAlgorithm.HS512, secretKey)
            .compact();
    }

    public String getUsernameFromToken(String token) {
        return Jwts.parser()
            .setSigningKey(secretKey)
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }
}

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    @Autowired
    private JwtTokenProvider jwtTokenProvider;
    @Autowired
    private AuthenticationManager authenticationManager;

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(
                loginRequest.getUsername(),
                loginRequest.getPassword()
            )
        );

        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        List<String> roles = userDetails.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.toList());

        String token = jwtTokenProvider.generateToken(
            userDetails.getUsername(),
            roles
        );

        return ResponseEntity.ok(
            new JwtAuthenticationResponse(token)
        );
    }
}

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {

        try {
            String token = extractTokenFromRequest(request);
            
            if (token != null && jwtTokenProvider.validateToken(token)) {
                String username = jwtTokenProvider.getUsernameFromToken(token);
                
                UserDetails userDetails = 
                    userDetailsService.loadUserByUsername(username);
                
                UsernamePasswordAuthenticationToken authentication = 
                    new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                    );
                
                SecurityContextHolder.getContext()
                    .setAuthentication(authentication);
            }
        } 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;
    }
}

Преимущества: масштабируемая, не требует session хранилища, работает с микросервисами Недостатки: сложнее реализовать logout, токен содержит данные (GDPR проблемы)

OAuth 2.0

OAuth 2.0 — стандарт для авторизации через третьи сервисы (Google, GitHub и т.д.):

@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/**")
            .authorizeRequests()
                .antMatchers("/", "/login**", "/webjars/**")
                .permitAll()
                .anyRequest()
                .authenticated()
            .and()
            .logout()
                .logoutSuccessUrl("/")
                .permitAll()
            .and()
            .csrf()
                .csrfTokenRepository(csrfTokenRepository());
    }
}

@SpringBootApplication
@EnableOAuth2Client
public class OAuth2ClientApplication {
    @Bean
    public OAuth2ClientContext oauth2ClientContext() {
        return new DefaultOAuth2ClientContext();
    }

    @Bean
    @ConfigurationProperties("security.oauth2.client")
    public ClientCredentialsResourceDetails clientCredentialsResourceDetails() {
        return new ClientCredentialsResourceDetails();
    }
}

application.yml:

security:
  oauth2:
    client:
      clientId: your-client-id
      clientSecret: your-client-secret
      accessTokenUri: https://accounts.google.com/o/oauth2/token
      userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
      tokenName: access_token
      authenticationScheme: query
      clientAuthenticationScheme: form
    resource:
      userInfoUri: https://www.googleapis.com/oauth2/v2/userinfo

Преимущества: стандартный способ, социальная интеграция, высокая безопасность Недостатки: сложнее настройка, зависимость от провайдера

SAML 2.0

SAML — корпоративный стандарт для SSO (Single Sign-On):

@Configuration
@EnableWebSecurity
public class SAMLSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public SAMLProcessingFilter samlProcessingFilter() throws Exception {
        SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
        samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
        samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(
            successRedirectHandler()
        );
        return samlWebSSOProcessingFilter;
    }

    @Bean
    public SAMLAuthenticationProvider samlAuthenticationProvider() {
        SAMLAuthenticationProvider samlAuthenticationProvider = 
            new SAMLAuthenticationProvider();
        samlAuthenticationProvider.setUserDetails(userDetailsService);
        return samlAuthenticationProvider;
    }
}

Преимущества: корпоративный стандарт, мощная аудит функциональность Недостатки: сложность, требует мета-данные провайдера

API Key Authentication

API Key — простой способ для машина-к-машина коммуникации:

@Component
public class ApiKeyAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    private ApiKeyValidator apiKeyValidator;

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {

        String apiKey = request.getHeader("X-API-Key");

        if (apiKey != null && apiKeyValidator.isValid(apiKey)) {
            ApiKeyAuthenticationToken authentication = 
                new ApiKeyAuthenticationToken(apiKey);
            authentication.setAuthenticated(true);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request, response);
    }
}

@Service
public class ApiKeyValidator {
    @Autowired
    private ApiKeyRepository apiKeyRepository;

    public boolean isValid(String apiKey) {
        ApiKey key = apiKeyRepository.findByKey(apiKey);
        return key != null && key.isActive() && key.notExpired();
    }
}

Преимущества: простая, эффективная для API Недостатки: нельзя разлогиниться, нет информации о пользователе

Сравнение методов

МетодСложностьМасштабируемостьLogoutКоробка
Basic AuthНизкаяСредняяСложныйДа
SessionСредняяНизкаяПростойДа
JWTСредняяВысокаяСложныйНет
OAuth 2.0ВысокаяВысокаяАвтоматическийДа
SAMLВысокаяВысокаяАвтоматическийДа
API KeyНизкаяВысокаяN/AНет

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

  • Web приложения — Session auth или OAuth2
  • REST API — JWT или API Key
  • Микросервисы — JWT + Service-to-Service OAuth2
  • Корпоративные системы — SAML 2.0
  • Мобильные приложения — JWT или OAuth2