본문 바로가기
이직&취업/Spring Framework

Spring Security 완벽 가이드: 인증과 인가를 한 번에 끝내는 보안 솔루션!

by journeylabs 2025. 4. 28.
728x90
반응형

목차

     

    Spring Security는 Spring Framework 기반 애플리케이션의 보안을 처리하는 강력한 프레임워크입니다. 인증(Authentication)과 인가(Authorization)를 비롯한 다양한 보안 기능을 제공하며, 웹 애플리케이션의 보안을 간편하고 안전하게 구현할 수 있습니다. 이 글에서는 Spring Security의 주요 개념, 특징, 원리, 실무 활용 사례, 장단점, 그리고 주의사항을 자세히 다뤄보겠습니다. 초보자부터 실무 개발자까지 쉽게 이해할 수 있도록 구성했으니, Spring Security를 완벽히 마스터하고 싶다면 끝까지 읽어보세요!


    1. Spring Security란? 주요 개념 및 용어

     

    Spring Security의 정의

    Spring Security는 Spring 기반 애플리케이션에서 보안 처리를 위한 프레임워크로, 인증, 인가, 세션 관리, CSRF 방지 등 다양한 보안 기능을 제공합니다. 웹 애플리케이션, REST API, 마이크로서비스 등에서 광범위하게 사용됩니다.

     

    주요 용어

    • 인증(Authentication): 사용자가 누구인지 확인하는 과정(예: 로그인).
    • 인가(Authorization): 인증된 사용자가 특정 자원에 접근할 권한이 있는지 확인.
    • Security Filter Chain: Spring Security의 핵심 구조로, HTTP 요청을 처리하는 필터 체인.
    • UserDetails: 사용자 정보(아이디, 비밀번호, 권한 등)를 정의하는 인터페이스.
    • PasswordEncoder: 비밀번호를 안전하게 암호화하는 도구.
    • CSRF(Cross-Site Request Forgery): 악의적인 사이트에서 사용자의 권한으로 요청을 위조하는 공격.
    • OAuth2: 타사 애플리케이션(Google, GitHub 등)을 통한 인증 프로토콜.

    Spring Security의 특징

    • 강력한 인증/인가: 다양한 인증 방식(폼 로그인, OAuth2, JWT 등)과 세밀한 권한 관리 지원.
    • 유연한 확장성: 커스텀 필터, 사용자 정의 인증 로직 추가 가능.
    • 통합성: Spring Boot, Spring MVC 등 Spring 생태계와 원활히 통합.
    • 보안 기능: CSRF, XSS, 세션 고정(Session Fixation) 방지 등 기본 제공.
    • REST API 지원: 토큰 기반 인증(JWT, OAuth2)으로 헤드리스 애플리케이션 보안 처리.

    Spring Security vs 다른 보안 프레임워크

    • Spring Security: Spring 생태계에 최적화, 유연성과 확장성 뛰어남. 복잡한 설정 가능.
    • Shiro: 경량 프레임워크, 간단한 애플리케이션에 적합. Spring 통합 제한적.
    • Keycloak: OAuth2, OpenID Connect에 특화된 SSO 솔루션. 설정 간단 but 무거움.

    2. Spring Security의 원리와 구조

    Spring Security의 원리

    Spring Security는 필터 기반 아키텍처를 사용해 HTTP 요청을 가로채고 보안 로직을 적용합니다. 주요 구성 요소는 다음과 같습니다:

    • Security Filter Chain: HTTP 요청을 처리하는 필터 체인. UsernamePasswordAuthenticationFilter, CsrfFilter 등 다양한 필터 포함.
    • AuthenticationManager: 인증 요청을 처리하며, UserDetailsService와 PasswordEncoder를 사용해 사용자 정보 확인.
    • SecurityContext: 인증된 사용자 정보를 저장하는 컨텍스트. 스레드 로컬에 저장되어 애플리케이션 전반에서 사용.
    • AccessDecisionManager: 인가 결정을 내려 사용자의 권한을 확인.

    동작 흐름 (간소화)

    1. 클라이언트가 HTTP 요청 전송.
    2. Security Filter Chain이 요청 가로채기.
    3. 인증 필요 시 AuthenticationManager가 사용자 인증.
    4. 인가 확인 후 자원 접근 허용/거부.
    5. SecurityContext에 인증 정보 저장.
    

    Spring Security 설정 예시

    기본적인 Spring Security 설정은 @EnableWebSecuritySecurityFilterChain을 사용합니다.

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {
    
        @Bean
        public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
            http
                .authorizeHttpRequests(auth -> auth
                    .requestMatchers("/admin/**").hasRole("ADMIN")
                    .requestMatchers("/user/**").hasRole("USER")
                    .requestMatchers("/login", "/resources/**").permitAll()
                    .anyRequest().authenticated()
                )
                .formLogin(form -> form
                    .loginPage("/login")
                    .defaultSuccessUrl("/home")
                    .permitAll()
                )
                .logout(logout -> logout
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/login")
                    .permitAll()
                )
                .csrf(csrf -> csrf.disable()); // 개발용, 실무에서는 주의
            return http.build();
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
    • 설명:
      • authorizeHttpRequests: URL별 권한 설정. /admin/**은 ADMIN 역할, /user/**는 USER 역할만 접근 가능.
      • formLogin: 커스텀 로그인 페이지(/login)와 성공 시 이동 페이지(/home) 설정.
      • logout: 로그아웃 URL과 성공 후 이동 페이지 설정.
      • csrf.disable(): CSRF 보호 비활성화(개발용, 실무에서는 활성화 권장).
      • PasswordEncoder: 비밀번호를 BCrypt로 암호화.
    • 코드 정밀 설명

     

    사용자 인증 구현

    UserDetailsService를 커스터마이징해 사용자 데이터를 로드합니다.

    @Service
    public class CustomUserDetailsService implements UserDetailsService {
    
        @Autowired
        private UserRepository userRepository;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
            return new org.springframework.security.core.userdetails.User(
                user.getUsername(),
                user.getPassword(),
                Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + user.getRole()))
            );
        }
    }
    • 설명: UserDetailsService를 구현해 DB에서 사용자 정보를 로드. User 객체에 사용자 이름, 암호화된 비밀번호, 권한 목록을 반환.

    3. 실무에서 Spring Security 활용 사례

    Spring Security는 웹 애플리케이션, REST API, 마이크로서비스 등 다양한 환경에서 사용됩니다.

    3.1. Spring Boot 웹 애플리케이션 보안

    Spring Boot 애플리케이션에서 사용자 인증과 권한 관리를 구현합니다.

     

    예시: 역할 기반 접근 제어

    @RestController
    public class UserController {
    
        @GetMapping("/user/profile")
        @PreAuthorize("hasRole('USER')")
        public String getUserProfile() {
            return "User profile page";
        }
    
        @GetMapping("/admin/dashboard")
        @PreAuthorize("hasRole('ADMIN')")
        public String getAdminDashboard() {
            return "Admin dashboard";
        }
    }
    
    • 설명: @PreAuthorize로 메서드 레벨에서 권한 검사. USER 역할은 /user/profile, ADMIN 역할은 /admin/dashboard에만 접근 가능.

    3.2. JWT 기반 REST API 보안

    Spring Security와 JWT(JSON Web Token)를 조합해 stateless REST API를 보호합니다.

     

    예시: JWT 인증 필터

    public class JwtAuthenticationFilter extends OncePerRequestFilter {
        private final JwtTokenProvider tokenProvider;
    
        public JwtAuthenticationFilter(JwtTokenProvider tokenProvider) {
            this.tokenProvider = tokenProvider;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            String token = resolveToken(request);
            if (token != null && tokenProvider.validateToken(token)) {
                Authentication auth = tokenProvider.getAuthentication(token);
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
            filterChain.doFilter(request, response);
        }
    
        private String resolveToken(HttpServletRequest request) {
            String bearerToken = request.getHeader("Authorization");
            if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
                return bearerToken.substring(7);
            }
            return null;
        }
    }

     

    Security 설정

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {
    
        @Bean
        public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtTokenProvider tokenProvider) throws Exception {
            http
                .csrf(csrf -> csrf.disable())
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(auth -> auth
                    .requestMatchers("/auth/login").permitAll()
                    .anyRequest().authenticated()
                )
                .addFilterBefore(new JwtAuthenticationFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class);
            return http.build();
        }
    }
    • 설명: JwtAuthenticationFilter는 요청 헤더에서 JWT를 추출해 유효성 검사 후 인증 정보 설정. STATELESS 세션 정책으로 세션 없이 JWT로 인증 처리.

    3.3. OAuth2를 사용한 소셜 로그인

    Spring Security는 OAuth2를 통해 Google, GitHub 등의 소셜 로그인을 지원합니다.

     

    예시: OAuth2 설정

    spring:
      security:
        oauth2:
          client:
            registration:
              google:
                client-id: your-google-client-id
                client-secret: your-google-client-secret
                scope: profile,email
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {
    
        @Bean
        public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
            http
                .authorizeHttpRequests(auth -> auth
                    .requestMatchers("/login", "/oauth2/**").permitAll()
                    .anyRequest().authenticated()
                )
                .oauth2Login(oauth2 -> oauth2
                    .loginPage("/login")
                    .defaultSuccessUrl("/home")
                );
            return-http.build();
        }
    }
    • 설명: oauth2Login으로 Google 로그인을 설정. 사용자가 /login에서 Google로 로그인 후 /home으로 리다이렉트.

    4. Spring Security의 장점과 단점

    장점

    • 강력한 보안 기능: 인증, 인가, CSRF, XSS 방지 등 포괄적인 보안 제공.
    • 유연한 커스터마이징: 커스텀 필터, 인증 제공자 추가로 다양한 요구사항 충족.
    • Spring 통합: Spring Boot, Spring MVC와 원활히 통합.
    • 다양한 인증 지원: 폼 로그인, JWT, OAuth2, SAML 등 지원.
    • 커뮤니티 지원: 활발한 커뮤니티와 풍부한 문서.

    단점

    • 학습 곡선: 복잡한 설정과 개념 이해에 시간 필요.
    • 설정 복잡성: 고급 기능 사용 시 설정이 복잡해질 수 있음.
    • 성능 오버헤드: 필터 체인과 암호화로 인해 약간의 성능 저하 가능.
    • 초기 설정 비용: 소규모 프로젝트에서는 과도한 설정 필요.

    주의사항

    • CSRF 활성화: REST API가 아닌 웹 애플리케이션에서는 CSRF 보호 활성화 필수.
    • 비밀번호 암호화: BCryptPasswordEncoder 등 안전한 암호화 사용.
    • 세션 관리: 동시 세션 제한, 세션 만료 시간 설정으로 보안 강화.
    • HTTPS 강제: 민감한 데이터 전송 시 HTTPS를 사용하도록 설정.
    • 테스트 철저히: 보안 설정 변경 후 인증/인가 테스트 필수.
    • 문서화: 커스텀 설정과 인증 로직을 명확히 문서화.

    5. 결론

    Spring SecuritySpring 기반 애플리케이션의 보안을 처리하는 강력하고 유연한 프레임워크입니다. form 로그인, JWT, OAuth2 등 다양한 인증 방식을 지원하며, 웹 애플리케이션과 REST API에서 안정적인 보안을 제공합니다. 설정의 복잡성과 학습 곡선이 있지만, Spring 생태계와의 통합성과 확장성으로 인해 실무에서 필수적인 도구로 자리 잡았습니다. 적절한 설정과 주의사항을 준수하면 안전하고 효율적인 애플리케이션을 구축할 수 있습니다.

    이 글을 통해 Spring Security의 개념부터 실무 활용까지 완벽히 이해하셨길 바랍니다. Spring Security를 활용해 더 안전한 애플리케이션을 만들어보세요!

    728x90
    반응형