Spring Security

2023. 4. 3. 17:25Spring

728x90

스프링 시큐리티

스프링 기반의 애플리케이션의 보안(인증, 권한, 인가 등)을 담당하는 스프링 하위 프레임워크

장점 :

보안 관련해서 체계적으로 많은 옵션 제공

개발자가 보안 로직을 일일이 작성하지 않아도 됨

기본 용어

접근 주체 : 보호된 리소스에 접근하는 대상

인증 : 보호된 리소스에접근한 대상에 대해 누구인지, 래플리케이션의 작업을 수행해도 되는 주체인지 확인하는 과정

인가 : 해당 리소스에 대해 접근 가능한 권한을 가지고 있는 지 확인하는 과정

권한 : 인가 과정에서 해당 리소스에 대한 제한된 최소한의 권한을 가졌는지 확인

동작

1. HTTP 요청 수신

  • 클라이언트로 부터 요청이 오면 인증 및 권한 부여 목적으로 일련의 필터를 거치게 됨

2. UsernamePasswordAuthentication Filter

  • 요청이 UsernamePasswordAuthentication Token에 도착하면 해당 클래스의 attempAuthentication(request, response) 메서드가 동작
  • attempAuthentication(request, response) :
  • request로 부터 username, password를 가져와 사용자 자격 증명을 기반으로한 UsernamePasswordAuthentication Token을 생성

3. AuthenticationManager

  • 생성된 토큰을 가지고 AuthenticationManager에게 인증 진행하도록 위임 (AuthenticationManager의 실질적 구현체 : ProviderManager)

4. AuthenticationProvider

  • AuthenticationManager로부터 인증 진행을 위임 받은 ProviderManager는 여러 AuthenticationProvider를 순회하면서 UsernamePasswordAuthenticationToken을 처리해줄 Authentication Provider를 탐색

5. UserDetailsService, UserDetails

  • DB에서 사용자 인증 정보를 가져올 UserDetailsService 객체에게 사용자 아이디를 넘겨주고, DB에서 인증에 사용할 사용자 정보를 UserDetails라는 객체로 전달 받음

6. AutheticationProvider

  • AuthenticationProvider는 UserDetails 객체를 전달 받은 이후 실제 사용자의 입력 정보와 UserDetails 객체를 가지고 인증을 시도

7. SecurityContextHolder

  • 인증이 완료되면 사용자 정보를 가진 Authentication 객체를 SecurityContextHolder에 담은 후 AuthenticationSuccessHandle을 실행

 

Springboot 적용

1. dependency 추가

dependencies {
	compile "org.springframework.boot:spring-boot-starter-security"
}

 

2. 개발시 로그인 폼 해결방법

1) 기본 사용자 계정 등록

// application.yml

spring:
  security: # 개발시 login폼 기본 사용자 계정 사용
    user:
      name: admin
      password: password

2) @EnableAuthoConfiguration의 exclude 속성 사용하여 SecurityAutoConfiguration 중지

@SpringBootApplication
@EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class})

 

3. Config

Spring Security 5.7 이상에서 WebSecurityConfigurerAdapter 사용 권장 하지 않음 → SecurityFilterChain Bean 등록 하는 방법 사용

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터 체인에 등록됨
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    // 인증, 인가 서비스가 필요하지 않은 endpoin 적용
    @Bean
    public WebSecurityCustomizer configure(){
        return (web) -> web.ignoring()
                .antMatchers(
                        "/swagger-ui.html"
                );
    }
		
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .csrf().disable() // csrf 비활성화
                .headers().frameOptions().sameOrigin() // 동일 도메인에서는 X-Frame-Option 활성화

                .and()
                .authorizeRequests() // 요청에 의한 보안 검사 시작
                .antMatchers(
                        "/api/v1/login"
                ).permitAll() //antMatchers 에 설정한 리소스의 접근을 인증 절차 없이 허용

                .anyRequest().authenticated() // 위에서 설정하지 않은 나머지 부분들은 인증 절차 수행
                .and()
                .build();
    }
}

 

스프링 시큐리티 설정 방법

리소스의 권한 설정

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http                
                .authorizeRequests() // 요청에 의한 보안 검사 시작
                .antMatchers(
                        "/api/v1/login"
                ).permitAll() //antMatchers 에 설정한 리소스의 접근을 인증 절차 없이 허용

                .anyRequest().authenticated() // 위에서 설정하지 않은 나머지 부분들은 인증 절차 수행
                .and()
                .build();
    }

antMatchers

특정 리소스에 대해서 권한 설정

antMatchers("/login**", "/web-resources/**", "/actuator/**")

permitAll

antMatchers 설정한 리소스의 접근을 인증 절차 없이 허용

antMatchers("/login**", "/web-resources/**", "/actuator/**").permitAll()

hasAnyRole

antMatchers 설정한 리소스의 접근시 해당 레벨의 권한을 가진 사용자만 접근 허용

antMatchers("/admin/**").hasAnyRole("ADMIN")

anyRequest

나머지 리소스들은 무조건 인증을 완료해야 접근이 가능

anyRequest().authenticated()

커스텀 필터 등록

addFilterBefore

지정된 필터 앞에 커스텀 필터를 추가

UsernamePasswordAuthenticationFilter 보다 먼저 실행됨

public void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new 커스텀 필터("/login-process"), 
                UsernamePasswordAuthenticationFilter.class);         
    }

addFilterAfter

지정된 필터 뒤에 커스텀 필터를 추가

UsernamePasswordAuthenticationFilter 이후에 실행됨

public void configure(HttpSecurity http) throws Exception {
        http.addFilterAfter(new 커스텀 필터("/login-process"), 
                UsernamePasswordAuthenticationFilter.class);
}

addFilterAt

지정된 필터의 순서에 커스텀 필터가 추가됨


참고자료

https://docs.spring.io/spring-security/reference/index.html

https://wildeveloperetrain.tistory.com/50

https://devuna.tistory.com/59

https://kimchanjung.github.io/programming/2020/07/02/spring-security-02/

'Spring' 카테고리의 다른 글

Spring Security Swagger 예외처리  (0) 2023.04.03
Spring Swagger  (0) 2023.04.03
JPA Mapping  (0) 2023.03.31
GenerationType  (0) 2023.03.31
Spring_Entity, DTO, VO  (0) 2023.03.22