← Назад к вопросам
Какую использовал систему авторизации на проекте?
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 | Монолиты, веб-приложения | Простая, из коробки | Привязана к серверу |
| JWT | REST 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
- Никогда не хранить пароли в открытом виде (используй BCrypt)
- HTTPS всегда — авторизация по HTTP = откровенная уязвимость
- Токены с коротким TTL — перевыпускать часто (15-30 минут)
- CSRF защита для форм (Spring Security автоматически)
- Логирование попыток входа — для анализа атак
- Rate limiting на /login endpoint — защита от brute force
- OAuth 2.0 для интеграций вместо обмена пароля