๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๊ฐœ๋ฐœ/Spring

Spring Security

by 1mj 2022. 3. 7.

Spring Security๋ž€?

Spring ๊ธฐ๋ฐ˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ณด์•ˆ(์ธ์ฆ๊ณผ ๊ถŒํ•œ, ์ธ๊ฐ€ ๋“ฑ)์„ ๋‹ด๋‹นํ•˜๋Š” ์Šคํ”„๋ง ํ•˜์œ„ ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค.

  • ์ฃผ๋กœ ์„œ๋ธ”๋ฆฟ ํ•„ํ„ฐ์™€ ์ด๋“ค๋กœ ๊ตฌ์„ฑ๋œ ํ•„ํ„ฐ ์ฒด์ธ์œผ๋กœ ๋˜์–ด์žˆ๋‹ค.
  • ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„๊ณ  Spring Security ํ”„๋กœ์„ธ์Šค์— ๋ณด์•ˆ ์ฒ˜๋ฆฌ๋ฅผ ์œ„์ž„ํ•˜๋Š” ์ผ๋ จ์˜ ๊ณผ์ •์„ ์˜๋ฏธํ•œ๋‹ค.
  • ์ธ์ฆ ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์นœ ํ›„ ์ธ๊ฐ€ ์ ˆ์ฐจ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ์•„์ด๋””(Principal), ๋น„๋ฐ€๋ฒˆํ˜ธ(Credential)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Credential ๊ธฐ๋ฐ˜์˜ ์ธ์ฆ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๊ธฐ๋ณธ์ ์œผ๋กœ ์ธ์ฆ ์ •๋ณด๋Š” ์ธ๋ฉ”๋ชจ๋ฆฌ ์„ธ์…˜ ์ €์žฅ์†Œ์ธ SecurityContextHolder์— ์„ธ์…˜-์ฟ ํ‚ค ๋ฐฉ์‹์œผ๋กœ ์ €์žฅ๋œ๋‹ค.
  • Security 3.2 ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” xml๋กœ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  ์ž๋ฐ” bean์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•œ๋‹ค.
๐Ÿ”Ž ์ธ์ฆ(Authentication)
์‚ฌ์šฉ์ž๊ฐ€ ๋ณธ์ธ์ด ๋งž๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ ˆ์ฐจ
๐Ÿ”Ž ์ธ๊ฐ€(Authorization)
์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ ์ž์›์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธํ•˜๋Š” ์ ˆ์ฐจ
๐Ÿ”Ž ์ ‘๊ทผ ์ฃผ์ฒด(Principal)
๋ณดํ˜ธ ๋ฐ›๋Š” ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•˜๋Š” ๋Œ€์ƒ

 

Spring Security ๋™์ž‘ ๊ณผ์ •

๐Ÿ”Ž ์„ธ์…˜-์ฟ ํ‚ค ์ธ์ฆ ๊ณผ์ •
โ‘  ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•˜๋ฉด http request ์š”์ฒญ์ด ๋“ค์–ด์˜จ๋‹ค.
โ‘ก AuthenticationFilter๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ์ €์žฅ๋œ DB์—์„œ ์ •๋ณด๋ฅผ ์กฐํšŒํ•œ๋‹ค.
โ‘ข DB์— ์ •๋ณด๊ฐ€ ์žˆ๋Š” ์‚ฌ์šฉ์ž๋Š” UserDetails๋กœ ์„ธ์…˜์„ ์ƒ์„ฑํ•œ๋‹ค.
โ‘ฃ Spring Security ์ธ๋ฉ”๋ชจ๋ฆฌ ์„ธ์…˜ ์ €์žฅ์†Œ์ธ SecurityContextHolder์— ์ €์žฅํ•œ๋‹ค.
โ‘ค ์‚ฌ์šฉ์ž์—๊ฒŒ ์„ธ์…˜ ID์™€ ํ•จ๊ป˜ ์‘๋‹ต์„ ํ•œ๋‹ค.
โ‘ฅ ์ดํ›„ ์š”์ฒญ์—์„œ๋Š” ์ฟ ํ‚ค์—์„œ ์„ธ์…˜ ID๋ฅผ ๊ฒ€์ฆํ•˜๊ณ  ์œ ํšจํ•  ๊ฒฝ์šฐ ์ธ์ฆ๋œ๋‹ค.

 

Spring Security Filter ์ข…๋ฅ˜

HeaderWriterFilter ์‘๋‹ต ํ—ค๋”์— ์‹œํ๋ฆฌํ‹ฐ ๊ด€๋ จ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” ์—ญํ• 
CorsFilter Cross-Domain ์š”์ฒญ์ธ์ง€๋ฅผ ํ™•์ธํ•˜๊ณ  ์‹ค์ œ ์š”์ฒญ ํŽ˜์ด์ง€์— ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ์ ์ ˆํ•œ CORS ์ •์ฑ…๊ณผ ํ—ค๋”๋ฅผ ์ ์šฉ
CsrfFilter CSRF ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•˜๋Š” ์—ญํ• , CSRF Token์„ ํ™œ์šฉํ•˜์—ฌ ๋ฐฉ์–ด
LogoutFilter ๋กœ๊ทธ์•„์›ƒ ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ LogoutHandler๊ฐ€ ๋กœ๊ทธ์•„์›ƒ ์ˆ˜ํ–‰
UsernamePasswordAuthenticationFilter ์‚ฌ์šฉ์ž ์ธ์ฆ์„ ์ฒ˜๋ฆฌ, ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ username๊ณผ password๋กœ UsernamePasswordAuthenticationToken์„ ๋งŒ๋“ค๊ณ   AuthenticationManager๋ฅผ ํ†ตํ•ด ์ธ์ฆ ์ฒ˜๋ฆฌ
ConcurrentSessionFilter ๋งค ์š”์ฒญ๋งˆ๋‹ค ํ˜„์žฌ ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜ ๋งŒ๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํ™•์ธ
BearerTokenAuthenticationFilter BearerToken์— ๋Œ€ํ•ด์„œ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ์—ญํ•  ๋‹ด๋‹น, JWT๋กœ ์ธ์ฆ๋œ ์š”์ฒญ์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌ
BasicAuthenticationFilter Http Basic ์ธ์ฆ์„ ์ฒ˜๋ฆฌ, Authorization ํ•ด๋”์— Basic ํ† ํฐ์„ ์ธ์ฆํ•ด์ฃผ๋Š” ์—ญํ• 
RequestCacheAwareFilter request ๋‚ด์šฉ์„ cache์— ์ €์žฅํ•ด๋†“๊ณ  ๋‹ค์Œ request๊ฐ€ ์˜ค๋ฉด ์ด์ „์˜ cache ๊ฐ’์„ ์ „๋‹ฌ
RememberMeAuthenticationFilter ์„ธ์…˜์ด ๋งŒ๋ฃŒ๋˜๊ฑฐ๋‚˜ ์ข…๋ฃŒ๋œ ํ›„์—๋„ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์ธ์ฆ ์œ ๋ฌด๋ฅผ ๊ธฐ์–ตํ•˜๋Š” ์—ญํ• , ์ฟ ํ‚ค๋ฅผ ๊ฒ€์‚ฌํ•ด ์ธ์ฆ ์ฒ˜๋ฆฌ
SessionManagementFilter ์„ธ์…˜ ๋ณ€์กฐ ๋ฐฉ์ง€ ์ „๋žต ์„ค์ •, ์œ ํšจํ•˜์ง€ ์•Š์€ ์„ธ์…˜ Redirect URL ์„ค์ •, ๋™์‹œ์„ฑ ์ œ์–ด ๋“ฑ ์„ธ์…˜ ์ •์ฑ…์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌ
ExcpetionTranslationFilter  ํ•ด๋‹น ํ•„ํ„ฐ ์ดํ›„ ์ธ์ฆ์ด๋‚˜ ๊ถŒํ•œ ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ์ฒ˜๋ฆฌ, ExceptionTranslationFilter๊ฐ€ SecurityInterceptor ์ด์ „์— ์กด์žฌํ•ด์•ผ ํ•จ

 

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—์„œ ํ•„ํ„ฐ ํ˜ธ์ถœ ์ˆœ์„œ ๋””๋ฒ„๊น…์ด ํ•„์š”ํ•  ๋•Œ๋Š” ๋””๋ฒ„๊ทธ ๋ชจ๋“œ๋ฅผ ํ™œ์„ฑํ™”ํ•˜์—ฌ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ‘† ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•; @EnableWebSecurity

WebSecurityConfigureAdapter๋ฅผ ์ƒ์†๋ฐ›์•„ Filter Chain์„ ๋งŒ๋“œ๋Š” ํด๋ž˜์Šค์— @EnableWebSecurity(debug=true) ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ์ฃผ๋ฉด ์š”์ฒญ URL, ์„ธ์…˜ ID, ์š”์ฒญ ๋ธŒ๋ผ์šฐ์ € ๋“ฑ์˜ ์ •๋ณด์™€ ํ˜„์žฌ ์‹คํ–‰๋˜๋Š” Security Filter๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

โœŒ ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•; ์„ค์ •ํŒŒ์ผ ๋‚ด spring.security.debug๋ฅผ true๋กœ ์„ค์ •

@Value ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•ด ์„ค์ • ๊ฐ’์„ ๋™์ ์œผ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค. :false๋ฅผ ํ•ด์ฃผ๋ฉด ์„ค์ •์ด ์—†์„ ๊ฒฝ์šฐ false๊ฐ€ ๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ ์ง€์ •๋œ๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค์ •ํŒŒ์ผ์„ ์ด์šฉํ•˜๋ฉด ํ™˜๊ฒฝ ๋ณ„๋กœ ์„ค์ • ๊ฐ’์„ ๋‹ค๋ฅด๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${spring.security.debug:false}")
    boolean securityDebug;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.debug(securityDebug);
    }
}

 

Spring Security ๊ตฌํ˜„

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋ฒ„๊ฐ€ ๊ธฐ๋™๋  ๋•Œ ์‹œํ๋ฆฌํ‹ฐ ์ดˆ๊ธฐํ™” ์ž‘์—… ๋ฐ ๊ธฐ๋ณธ์ ์ธ ๋ณด์•ˆ ์„ค์ •์ด ์ด๋ฃจ์–ด์ง„๋‹ค.

  • ๊ธฐ๋ณธ์ ์ธ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋ฅผ ์ œ๊ณต, ์š”์ฒญ์— ๋Œ€ํ•œ ์ธ์ฆ์„ ์š”๊ตฌ
  • ์ธ์ฆ ๋ฐฉ์‹์€ Form ๋กœ๊ทธ์ธ ๋ฐฉ์‹๊ณผ httpBasic ๋กœ๊ทธ์ธ ๋ฐฉ์‹ ์ œ๊ณต
  • Form ๋กœ๊ทธ์ธ ๋ฐฉ์‹์€ ์„œ๋ฒ„์— ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜ ์ƒํƒœ๊ฐ€ ์œ ํšจํ•œ์ง€๋ฅผ ํŒ๋‹จํ•˜์—ฌ ์ธ์ฆ ์ฒ˜๋ฆฌ
  • Http Basic ๋กœ๊ทธ์ธ ๋ฐฉ์‹์€ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์š”์ฒญ๋ฐ›์€ ๋ฐฉ์‹๋Œ€๋กœ ๊ตฌ์„ฑํ•œ ๋‹ค์Œ ํ—ค๋”์— ๊ธฐ์ˆ ํ•˜์—ฌ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ์ธ์ฆ ์ฒ˜๋ฆฌ

โœ” Maven or Gradle

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

compile("org.springframework.boot:spring-boot-starter-security")

 

 

โœ” WebSecurityConfigurerAdapter

  • ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์˜ ์›น ๋ณด์•ˆ ๊ธฐ๋Šฅ์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์„ค์ •ํ•ด์ฃผ๋Š” ์ถ”์ƒ ํด๋ž˜์Šค
  • ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์•„ config ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„
  • @EnableWebSecurity ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•˜๋ฉด ์›น ๋ณด์•ˆ์„ ํ™œ์„ฑ์‹œ์ผœ Spring Security Filter๊ฐ€ ์ž๋™์œผ๋กœ ํฌํ•จ
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    // ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•˜๋Š” ๋ฐฉ๋ฒ•
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    	// AuthenticationProvider ๊ตฌํ˜„์ฒด
        auth.authenticationProvider(authenticationProvider);
        // auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    // ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ๊ทœ์น™์„ ๋ฌด์‹œํ•˜๋Š” url ์ง€์ •
    @Override
    public void configure(WebSecurity web) throws Exception {
    	web.ignoring()
        	.antMatchers("/resources/**")
            .antMatchers("/css/**")
            .antMatchers("/vendor/**")
            .antMatchers("/js/**")
            .antMatchers("/favicon*/**")
            .antMatchers("/img/**");
    }

    // ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ๊ทœ์น™
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	http.authorizeRequests()	// ๋ณดํ˜ธ๋œ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ ์„ค์ •
        	.antMatchers("/login*/**").permitAll() // ์ „์ฒด ์ ‘๊ทผ ํ—ˆ์šฉ
            .antMatchers("/logout/**").permitAll()
            .antMatchers("/info").hasRole("ADMIN")// ADMIN ๋กค์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผ ํ—ˆ์šฉ
            .anyRequest().authenticated()
          .and().logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler())
          .and().csrf().disable()	// csrf ๋ณด์•ˆ ์„ค์ •์„ ๋น„ํ™œ์„ฑํ™”
          .exceptionHandling()
          .accessDeniedHandler(accessDeniedHandler())
          .authenticationEntryPoint(authenticationEntryPoint());
   }
}

 

์ฐธ๊ณ ์ž๋ฃŒ ๋ฐ ์ถœ์ฒ˜ ๐Ÿ™‡‍โ™‚๏ธ

https://sjh836.tistory.com/165

https://velog.io/@seongwon97/Spring-Security-Filter%EB%9E%80

https://devuna.tistory.com/59

 

๋Œ“๊ธ€