[8/3 TIL] SPRING SECURITY(SecurityContextHolderFilter, SessionManagementFilter, ์ธ๊ฐ€ ์ฒ˜๋ฆฌ)

yumyeonghanยท2023๋…„ 8์›” 6์ผ
0

๐Ÿƒํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐฑ์—”๋“œ ๋ฐ๋ธŒ์ฝ”์Šค 4๊ธฐ ๊ต์œก๊ณผ์ •์„ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.๐Ÿƒ

SecurityContextHolderFilter

  • SecurityContextRepository ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์˜ SecurityContext๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ๊ฐฑ์‹ ํ•จ
    • ์ธ์ฆ ๊ด€๋ จ ํ•„ํ„ฐ ์ค‘ ๊ฐ€์žฅ ์ตœ ์ƒ๋‹จ์— ์œ„์น˜ํ•˜๋ฉฐ, ์ด๋ฏธ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋Š” ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•  ํ•„์š”๊ฐ€ ์—†์Œ
    • SecurityContext๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, empty SecurityContext๋ฅผ ์ƒ์„ฑํ•จ

๋™์ž‘๊ณผ์ •

  1. ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•˜์—ฌ ์ธ์ฆ ์ •๋ณด๋ฅผ ์ œ์ถœ
  2. UsernamePasswordAuthenticationFilter ๋˜๋Š” ๋‹ค๋ฅธ ์ธ์ฆ ํ•„ํ„ฐ๊ฐ€ ์‚ฌ์šฉ์ž์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , Authentication ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
  3. ์ธ์ฆ ๋งค๋‹ˆ์ €(AuthenticationManager)๋Š” ํ•ด๋‹น Authentication ๊ฐ์ฒด๋ฅผ ๊ฒ€์ฆํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ๋˜์—ˆ๋‹ค๊ณ  ํŒ๋‹จํ•˜๋ฉด, ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” SecurityContext ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
  4. SecurityContextHolderFilter๋Š” ์ƒ์„ฑ๋œ SecurityContext ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์™€์„œ, HttpSession์— ์ €์žฅ
  5. ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋Š” ํ•ด๋‹น ์„ธ์…˜์—์„œ ๋‹ค๋ฅธ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ๋งˆ๋‹ค, SecurityContextHolderFilter๊ฐ€ ์š”์ฒญ์„ ์ˆ˜์‹ ํ•˜์—ฌ ํ•ด๋‹น ์„ธ์…˜์—์„œ SecurityContext ๊ฐ€์ ธ์˜ด
  6. ์‚ฌ์šฉ์ž๋Š” ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋กœ ๊ฐ„์ฃผ๋˜์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ณดํ˜ธ๋œ ์ž์›์— ์ ‘๊ทผ ๊ฐ€๋Šฅ

SessionManagementFilter

  • ์„ธ์…˜ ๊ณ ์ • ๋ณดํ˜ธ (session-fixation protection)
    • ์ธ์ฆ ์ „์— ๋ฐœ๊ธ‰ ๋ฐ›์€ ์„ธ์…˜ ID๊ฐ€ ์ธ์ฆ ํ›„์—๋„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋ฉด ์ •์ƒ ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜์„ ํƒˆ์ทจํ•˜์—ฌ ์ธ์ฆ์„ ์šฐํšŒํ•˜๊ณ , ์•…์˜์ ์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Œ
    • ์ฆ‰, ์ธ์ฆ ์ „์— ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋˜ ์„ธ์…˜์ด ์ธ์ฆ ํ›„์—๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š๋„๋ก ํ•˜๋ฉด ํ•ด๋‹น ๊ณต๊ฒฉ์— ํšจ๊ณผ์ ์œผ๋กœ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์Œ
    • Spring Security์—์„œ๋Š” 4๊ฐ€์ง€ ์„ค์ • ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์„ ์ œ๊ณต
      • none: ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์Œ (์„ธ์…˜์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•จ)
      • newSession: ์ƒˆ๋กœ์šด ์„ธ์…˜์„ ๋งŒ๋“ค๊ณ , ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋Š” ๋ณต์ œํ•˜์ง€ ์•Š์Œ
      • migrateSession: ์ƒˆ๋กœ์šด ์„ธ์…˜์„ ๋งŒ๋“ค๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๋ณต์ œํ•จ
      • changeSession: ์ƒˆ๋กœ์šด ์„ธ์…˜์„ ๋งŒ๋“ค์ง€ ์•Š์ง€๋งŒ, session-fixation ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•จ
  • ์œ ํšจํ•˜์ง€ ์•Š์€ ์„ธ์…˜ ๊ฐ์ง€ ์‹œ ์ง€์ •๋œ URL๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์‹œํ‚ด
  • ์„ธ์…˜ ์ƒ์„ฑ ์ „๋žต ์„ค์ •
    • IF_REQUIRED: ํ•„์š”์‹œ ์ƒ์„ฑํ•จ (๊ธฐ๋ณธ๊ฐ’)
    • NEVER: Spring Security์—์„œ๋Š” ์„ธ์…˜์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์ง€๋งŒ, ์„ธ์…˜์ด ์กด์žฌํ•˜๋ฉด ์‚ฌ์šฉํ•จ
    • STATELESS: ์„ธ์…˜์„ ์™„์ „ํžˆ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ (JWT ์ธ์ฆ์ด ์‚ฌ์šฉ๋˜๋Š” REST API ์„œ๋น„์Šค์— ์ ํ•ฉ)
    • ALWAYS: ํ•ญ์ƒ ์„ธ์…˜์„ ์‚ฌ์šฉํ•จ
  • ๋™์ผ ์‚ฌ์šฉ์ž์˜ ์ค‘๋ณต ๋กœ๊ทธ์ธ ๊ฐ์ง€ ๋ฐ ์ฒ˜๋ฆฌ
    • maximumSessions: ๋™์ผ ์‚ฌ์šฉ์ž์˜ ์ตœ๋Œ€ ๋™์‹œ ์„ธ์…˜ ๊ฐฏ์ˆ˜
    • maxSessionsPreventsLogin: ์ตœ๋Œ€ ๊ฐฏ์ˆ˜๋ฅผ ์ดˆ๊ณผํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ ์ธ์ฆ ์‹œ๋„๋ฅผ ์ฐจ๋‹จํ• ์ง€ ์—ฌ๋ถ€ (๊ธฐ๋ณธ๊ฐ’ false)
  • AbstractAuthenticationProcessingFilter ๊ฐ์ฒด๋Š” SessionManagementFilter์™€ ๋™์ผํ•œ ์„ธ์…˜ ๊ณ ์ • ๋ณดํ˜ธ, ์ตœ๋Œ€ ๋กœ๊ทธ์ธ ์„ธ์…˜ ์ œ์–ด๋ฅผ ์ˆ˜ํ–‰ํ•จ

Spring Security ์„ค์ •

	@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                //์ƒ๋žต 
                .sessionManagement(auth -> auth
                		.sessionFixation().changeSessionId() //session-fixation ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•˜๊ธฐ ์œ„ํ•ด ์„ธ์…˜ ID ๋ณ€๊ฒฝ
                        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) //์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ๋˜๋ฉด ์„ธ์…˜์„ ์ƒ์„ฑ
                        .invalidSessionUrl("/") //์„ธ์…˜์ด ๋๋‚ ๊ฒฝ์šฐ, ์‚ฌ์šฉ์ž๋ฅผ "/"๋กœ ์ด๋™์‹œํ‚ด
                        .maximumSessions(1) //๋™์‹œ ํ—ˆ์šฉ๋˜๋Š” ์„ธ์…˜ ์ˆ˜๋ฅผ 1๋กœ ์„ค์ •, ํ•œ ์‚ฌ์šฉ์ž๋งŒ ๋กœ๊ทธ์ธ ๊ฐ€๋Šฅ
                        .maxSessionsPreventsLogin(false)) //์ตœ๋Œ€ ์„ธ์…˜์ˆ˜์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ, ์ƒˆ๋กœ์šด ๋กœ๊ทธ์ธ์„ ํ—ˆ์šฉ(์ƒˆ ๋กœ๊ทธ์ธ์‹œ, ์ด์ „ ์„ธ์…˜์„ ๋งŒ๋ฃŒ)
               	.build();
    }
  • ๊ธฐ์กด SecurityFilterChain ๋นˆ์— SessionManagementFilter ์„ค์ •
  • http.sessionManagement()๋Š” ์‚ฌ์šฉ์ž ์„ธ์…˜๊ณผ ๊ด€๋ จ๋œ ๋ณด์•ˆ ์„ค์ •์„ ํ•˜๋Š” ์„ธ์…˜ ๊ด€๋ฆฌ์ž ์„ค์ •

์ธ๊ฐ€(Authorization) ์ฒ˜๋ฆฌ

  • ์ธ๊ฐ€(Authorization): ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋œ ์‚ฌ์šฉ์ž๋“ค๋งŒ ํŠน์ • ๊ธฐ๋Šฅ ๋˜๋Š” ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋ฉฐ, ์ด๋ฅผ ์œ„ํ•ด ์ธ๊ฐ€ ์ฒ˜๋ฆฌ๋Š” ๋‘ ๊ฐœ์˜ ์ž‘์—…์œผ๋กœ ๊ตฌ๋ถ„
    • ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์™€ ๊ถŒํ•œ(์—ญํ• )์„ ๋งคํ•‘: ROLE_USER, ROLE_ADMIN, ROLE_ANONYMOUS
    • ๋ณดํ˜ธ๋˜๋Š” ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ๊ถŒํ•œ ํ™•์ธ: ๊ด€๋ฆฌ์ž ๊ถŒํ•œ์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๋งŒ ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€์— ์ ‘๊ทผ ๊ฐ€๋Šฅ

FilterSecurityInterceptor

  • ํ•„ํ„ฐ ์ฒด์ธ ์ƒ์—์„œ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์œ„์น˜ํ•˜๋ฉฐ, ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ถŒํ•œ๊ณผ ๋ฆฌ์†Œ์Šค์—์„œ ์š”๊ตฌํ•˜๋Š” ๊ถŒํ•œ์„ ์ทจํ•ฉํ•˜์—ฌ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ• ์ง€ ๊ฒฐ์ •ํ•จ
    • ์‹ค์งˆ์ ์œผ๋กœ ์ ‘๊ทผ ํ—ˆ์šฉ ์—ฌ๋ถ€ ํŒ๋‹จ์€ AccessDecisionManager ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ฒด์—์„œ ์•„๋ž˜ 3๊ฐ€์ง€๋ฅผ ์ทจํ•ฉํ•˜์—ฌ ์ด๋ฃจ์–ด์ง
      • Authentication(์‚ฌ์šฉ์ž ๊ฐ์ฒด): SecurityContexHolder์—์„œ ๊ฐ€์ ธ์˜ด
      • FilterInvocation: ํ˜„์žฌ ์š”์ฒญ์— ๋Œ€ํ•œ ์ •๋ณด ์ œ๊ณต
      • ConfigAttributes(๋ฆฌ์†Œ์Šค์—์„œ ์š”๊ตฌํ•˜๋Š” ๊ถŒํ•œ): SecurityMetadataSource์—์„œ ๊ฐ€์ ธ์˜ด
  • FilterSecurityInterceptor ํ•„ํ„ฐ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์‹œ์ ์—์„œ ์‚ฌ์šฉ์ž๋Š” ์ด๋ฏธ ์ธ์ฆ์ด ์™„๋ฃŒ๋˜๊ณ , Authentication ์ธํ„ฐํŽ˜์ด์Šค์˜ getAuthorities() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ฌ์ˆ˜ ์žˆ์Œ
    • ์ด๋•Œ ์ต๋ช… ์‚ฌ์šฉ์ž๋„ ์ธ์ฆ์ด ์™„๋ฃŒ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•˜๋ฉฐ, ROLE_ANONYMOUS ๊ถŒํ•œ์„ ๊ฐ–์Œ
  • ๋ณดํ˜ธ๋˜๋Š” ๋ฆฌ์†Œ์Šค์—์„œ ์š”๊ตฌํ•˜๋Š” ๊ถŒํ•œ ์ •๋ณด๋Š” SecurityMetadataSource ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ConfigAttribute ํƒ€์ž…์œผ๋กœ ๊ฐ€์ ธ์˜ด

AccessDecisionManager ์ธํ„ฐํŽ˜์ด์Šค

  • ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ถŒํ•œ๊ณผ ๋ฆฌ์†Œ์Šค์—์„œ ์š”๊ตฌํ•˜๋Š” ๊ถŒํ•œ์„ ํ™•์ธํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ ์ ˆํ•œ ๊ถŒํ•œ์„ ๊ฐ–๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋ฉด ์ ‘๊ทผ ๊ฑฐ๋ถ€ ์ฒ˜๋ฆฌํ•จ
  • AccessDecisionVoter ๋ชฉ๋ก์„ ๊ฐ–๊ณ  ์žˆ์Œ
  • AccessDecisionVoter๋“ค์˜ ํˆฌํ‘œ(vote)๊ฒฐ๊ณผ๋ฅผ ์ทจํ•ฉํ•˜๊ณ , ์ ‘๊ทผ ์Šน์ธ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” 3๊ฐ€์ง€ ๊ตฌํ˜„์ฒด๋ฅผ ์ œ๊ณตํ•จ
    • AffirmativeBased: AccessDecisionVoter๊ฐ€ ์Šน์ธํ•˜๋ฉด ์ด์ „์— ๊ฑฐ๋ถ€๋œ ๋‚ด์šฉ๊ณผ ๊ด€๊ณ„์—†์ด ์ ‘๊ทผ์ด ์Šน์ธ๋จ (๊ธฐ๋ณธ๊ฐ’)
    • ConsensusBased: ๋‹ค์ˆ˜์˜ AccessDecisionVoter๊ฐ€ ์Šน์ธํ•˜๋ฉด ์ ‘๊ทผ์ด ์Šน์ธ๋จ
    • UnanimousBased: ๋ชจ๋“  AccessDecisionVoter๊ฐ€ ๋งŒ์žฅ์ผ์น˜๋กœ ์Šน์ธํ•ด์•ผ ์ ‘๊ทผ์ด ์Šน์ธ๋จ

AccessDecisionVoter ์ธํ„ฐํŽ˜์ด์Šค

int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1;

int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
  • AccessDecisionVoter๋Š” ์ ‘๊ทผ์„ ์Šน์ธํ• ์ง€ ๊ฑฐ์ ˆํ• ์ง€ ํ˜น์€ ๋ณด๋ฅ˜ํ• ์ง€ vote()๋กœ ํŒ๋‹จํ•จ
  • ๊ตฌํ˜„์ฒด๋กœ WebExpressionVoter๊ฐ€ ์žˆ์Œ

WebExpressionVoter ๊ตฌํ˜„์ฒด

  • SpEL ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•ด ์ ‘๊ทผ ์Šน์ธ ์—ฌ๋ถ€์— ๋Œ€ํ•œ ๊ทœ์น™์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ
  • SpEL ํ‘œํ˜„์‹ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด DefaultWebSecurityExpressionHandler ๊ทธ๋ฆฌ๊ณ  WebSecurityExpressionRoot ๊ตฌํ˜„์— ์˜์กดํ•จ
  • WebSecurityExpressionRoot ํด๋ž˜์Šค๋Š” SpEL ํ‘œํ˜„์‹์—์„œ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณต
profile
์›น ๊ฐœ๋ฐœ์— ๊ด€์‹ฌ ์žˆ์Šต๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€