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

Какую использовал систему авторизации на проекте?

1.3 Junior🔥 191 комментариев
#Soft Skills и карьера#Spring Framework#Безопасность

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

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

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

# Системы авторизации в Java проектах

Обзор типичных подходов

1. Spring Security (стандарт де-факто)

Самая популярная система авторизации в Java для веб-приложений:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/dashboard")
            .and()
            .logout()
                .logoutUrl("/logout");
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

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

  • Из коробки: аутентификация, авторизация, CSRF защита
  • Интеграция с DB через UserDetailsService
  • Role-based access control (RBAC)
  • Session управление

2. JWT (JSON Web Token)

Для REST API и микросервисов:

@Component
public class JwtProvider {
    
    private static final long EXPIRATION_TIME = 86400000; // 1 день
    private String jwtSecret = "secret-key";
    
    public String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
            .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 e) {
            return false;
        }
    }
}

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

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest request) {
        // Проверяем пароль
        Authentication auth = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(
                request.getUsername(),
                request.getPassword()
            )
        );
        
        String token = jwtProvider.generateToken(auth.getName());
        return ResponseEntity.ok(new JwtResponse(token));
    }
}

3. OAuth 2.0 / OpenID Connect

Для интеграции с соцсетями и сервисами:

@Configuration
@EnableOAuth2Client
public class OAuth2Config {
    
    @Bean
    public OAuth2RestTemplate oauth2RestTemplate(
            OAuth2ClientContext oauth2ClientContext,
            OAuth2ProtectedResourceDetails resource) {
        return new OAuth2RestTemplate(resource, oauth2ClientContext);
    }
}

@RestController
@RequestMapping("/login")
public class OAuth2LoginController {
    
    @GetMapping("/google")
    public void loginWithGoogle() {
        // Redirect к Google OAuth endpoint
    }
    
    @GetMapping("/google/callback")
    public ResponseEntity<?> googleCallback(@RequestParam String code) {
        // Обмениваем код на токен
        // Создаём пользователя если нового
        // Возвращаем JWT
        return ResponseEntity.ok(new JwtResponse(token));
    }
}

4. Session-based (традиционный подход)

Для монолитных веб-приложений:

@PostMapping("/login")
public String login(
        @RequestParam String username,
        @RequestParam String password,
        HttpSession session) {
    
    User user = userService.findByUsername(username);
    if (user != null && passwordEncoder.matches(password, user.getPassword())) {
        // Создаём сессию
        session.setAttribute("userId", user.getId());
        session.setAttribute("roles", user.getRoles());
        return "redirect:/dashboard";
    }
    
    return "redirect:/login?error=true";
}

@GetMapping("/dashboard")
public String dashboard(HttpSession session) {
    Object userId = session.getAttribute("userId");
    if (userId == null) {
        return "redirect:/login";  // Не авторизован
    }
    return "dashboard";  // Показываем страницу
}

5. SAML 2.0 (для энтерпрайза)

Для корпоративных приложений с SSO:

@Configuration
@EnableWebSecurity
public class SamlSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/saml/**").permitAll()
                .anyRequest().authenticated()
            .and()
            .apply(saml())
                .serviceProvider()
                    .protocol("https")
                    .hostname("app.example.com")
                    .basePath("/")
                .and()
                .identityProvider()
                    .metadataFilePath("classpath:idp-metadata.xml");
    }
}

Сравнение подходов

СистемаКогда использоватьПлюсыМинусы
Spring Security + SessionsМонолиты, веб-приложенияПростая, из коробкиПривязана к серверу
JWTREST API, микросервисыStateless, масштабируемоНет отзыва токена
OAuth 2.0Внешние сервисы, соцсетиБезопасно, стандартноСложнее настроить
SAMLЭнтерпрайз, SSOМощно для корпорацийТяжело, XML
KeycloakМикросервисы, SSOГотовое решение, полнофункциональноОтдельное разворачивание

Real-world пример: JWT + Spring Security

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        
        try {
            String jwt = getJwtFromRequest(request);
            
            if (jwt != null && jwtProvider.validateToken(jwt)) {
                String username = jwtProvider.getUsernameFromToken(jwt);
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                
                // Устанавливаем авторизацию в контекст
                UsernamePasswordAuthenticationToken auth =
                    new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
        } catch (Exception ex) {
            logger.error("Could not set user authentication", ex);
        }
        
        filterChain.doFilter(request, response);
    }
    
    private String getJwtFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

Best Practices

  1. Никогда не хранить пароли в открытом виде (используй BCrypt)
  2. HTTPS всегда — авторизация по HTTP = откровенная уязвимость
  3. Токены с коротким TTL — перевыпускать часто (15-30 минут)
  4. CSRF защита для форм (Spring Security автоматически)
  5. Логирование попыток входа — для анализа атак
  6. Rate limiting на /login endpoint — защита от brute force
  7. OAuth 2.0 для интеграций вместо обмена пароля
Какую использовал систему авторизации на проекте? | PrepBro