Spring Security ๋™์ž‘ ์›๋ฆฌ, ํ”„๋กœ์„ธ์Šค ์ดํ•ดํ•˜๊ธฐ

1. Spring Security ๊ฐœ์š”

 

Spring Security๋Š” ์œ„์™€ ๊ฐ™์ด ์ธ์ฆ๋ถ€ํ„ฐ ํŽธ์˜์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ, ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์•…์šฉ ๊ฐ€๋Šฅํ•œ ์„ธ์…˜ ๊ณ ์ •, ํด๋ฆญ์žฌํ‚น, ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์š”์ฒญ ์œ„์กฐ(CSRF) ๋“ฑ์˜ ๊ณต๊ฒฉ์œผ๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜๊นŒ์ง€ ํฌ๊ด„์ ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์€ ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Spring Security๋ฅผ ๋„์ž…ํ•˜๋ฉด ์ธ์ฆ,์ธ๊ฐ€ ๊ธฐ๋Šฅ์„ ํ‘œ์ค€ํ™” ํ•˜๊ณ  ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์–ด ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณด์•ˆ ๊ด€๋ จ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ๋†’์€ ์ˆ˜์ค€์˜ ๋ณด์•ˆ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.  

 

 

 

 

 

 

 

 

 

 

 

 

 

2. Spring Security ์ฃผ์š” ์•„ํ‚คํ…์ฒ˜

Spring ์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ์˜ ๋ชจ๋“  HTTP ์š”์ฒญ์€ Dispatcher Servlet์ด ๊ฐ€์žฅ ๋จผ์ € ์ˆ˜์‹ ํ•œ๋‹ค. ์ด๋Š” ์ˆ˜์‹ ํ•œ HTTP ์š”์ฒญ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ ์ ˆํ•œ ์ปจํŠธ๋กค๋Ÿฌ์— ์š”์ฒญ ์ฒ˜๋ฆฌ๋ฅผ ์œ„์ž„ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

 

๋˜ํ•œ, ์šด์˜ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ์„œ๋ฒ„๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉํ•ด์•ผ ํ•  ๋ถ€๊ฐ€ ์ž‘์—…์ด ์žˆ์„ ๋•Œ๋Š” DispatcherServlet ์ด์ „ ๋‹จ๊ณ„์— ์œ„์น˜ํ•œ Filter๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค. 

 

 

Filter๋Š” javax.servlet.Filter ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋กœ, HTTP ์š”์ฒญ์ด DispatcherServlet์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๊ฐ€๋กœ์ฑ„๊ณ  ๋ถ€๊ฐ€ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์œ„ ๊ทธ๋ฆผ์„ ๋ณด๋ฉด, DispatcherServlet์€ Java Spring ์ปจํ…Œ์ด๋„ˆ์˜ ๊ฐ€์žฅ ์•ž์— ์œ„์น˜ํ•˜์ง€๋งŒ, Spring Security Filter๋Š” Java Spring ์ปจํ…Œ์ด๋„ˆ ์•ž์— ์œ„์น˜ํ•œ๋‹ค. 

 

 

๋”ฐ๋ผ์„œ Filter ๋‹จ๊ณ„์—์„œ ์ธ์ฆ, ์ธ๊ฐ€, ๋กœ๊น… ๋“ฑ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด Java Spring ์ปจํ…Œ์ด๋„ˆ์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ๋ณด์•ˆ ์œ„ํ˜‘์„ ์ฐจ๋‹จํ•˜์—ฌ ์‹œ์Šคํ…œ ์•ˆ์ •์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

Spring Security๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด Filter๋ฅผ ํƒ€๋ฉฐ ์—ฌ๋Ÿฌ ๋ณด์•ˆ ๊ธฐ๋Šฅ๋“ค์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค. 

 

์•ž์„œ ๋งํ–ˆ๋“ฏ์ด Java Spring์˜ IoC ์ปจํ…Œ์ด๋„ˆ์™€๋Š” ๋ณ„๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ์ด๊ธฐ ๋•Œ๋ฌธ์— Java Spring์—์„œ ์ •์˜๋œ Bean์„ ์ฃผ์ž…๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

 

์›น ์ปจํ…Œ์ด๋„ˆ๋Š” DelegatingFilterProxy ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ Spring IoC ์ปจํ…Œ์ด๋„ˆ์— ์ •์˜๋œ ํŠน์ • Bean(SpringSecurityFilterChain)์—๊ฒŒ ์œ„์ž„ํ•จ์œผ๋กœ์จ, Java Spring์˜ DI์™€ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์›น ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ƒ์„ฑ๋œ Filter๊ฐ€ ์ง์ ‘ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋Œ€์‹  ํ•ด๋‹น Bean์ด ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค.

 

 

์ด๋Ÿฌํ•œ ํ๋ฆ„์„ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

1. ์‚ฌ์šฉ์ž๊ฐ€ ์ž์› ์š”์ฒญ 

 

2. Servlet Container์˜ ํ•„ํ„ฐ๋“ค์ด ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ๋˜๊ณ  ๊ทธ ์ค‘ DelegatingFilterProxy๊ฐ€ ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋  ๊ฒฝ์šฐ ์ž์‹ ์ด ์š”์ฒญ๋ฐ›์€ ์š”์ฒญ๊ฐ์ฒด๋ฅผ delegate request๋กœ ์š”์ฒญ ์œ„์ž„์„ ํ•œ๋‹ค.

 

3. ์š”์ฒญ ๊ฐ์ฒด๋Š” ํŠน์ •ํ•œ ํ•„ํ„ฐ(springSecurityFilterChain) ์—์„œ ๋ฐ›๊ฒŒ ๋œ๋‹ค.

 

4. FilterChainProxy์—์„œ๋Š” ์ž์‹ ์ด ๊ฐ€์ง„ ๊ฐ๊ฐ์˜ ํ•„ํ„ฐ๋“ค์„ ์ฐจ๋ก€๋Œ€๋กœ ์ˆ˜ํ–‰ํ•˜๋ฉฐ ๋ณด์•ˆ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

5. ๋ณด์•ˆ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ตœ์ข… ์ž์›์— ์š”์ฒญ์„ ์ „๋‹ฌํ•˜์—ฌ ๋‹ค์Œ ๋กœ์ง์ด ์ˆ˜ํ–‰๋œ๋‹ค.

 

 

 

 

 

 

 

 

 

3. ์ธ์ฆ ๊ฐ์ฒด ๊ด€๋ฆฌ

Authentication ์ธ์ฆ๊ฐ์ฒด๋ž€? 

๋‹น์‹ ์ด ๋ˆ„๊ตฌ์ธ์ง€ ์ฆ๋ช…ํ•˜๋Š” ๊ฒƒ ์‚ฌ์šฉ์ž์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ํ† ํฐ ๊ฐœ๋…์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. 

 

์ธ์ฆ ์‹œ id์™€ password๋ฅผ ๋‹ด๊ณ  ์ธ์ฆ ๊ฒ€์ฆ์„ ์œ„ํ•ด ์ „๋‹ฌ๋˜์–ด ์‚ฌ์šฉ๋œ๋‹ค. 

 

์ธ์ฆ ํ›„ ์ตœ์ข… ์ธ์ฆ ๊ฒฐ๊ณผ(user ๊ฐ์ฒด, ๊ถŒํ•œ ์ •๋ณด)๋ฅผ ๋‹ด๊ณ  SecurityContext ์— ์ €์žฅ๋˜์–ด ์ „์—ญ์ ์œผ๋กœ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

Authentication authentication = 
	SecurityContexHolder.getContext().getAuthentication();

 

 

 

Authentication ๊ฐ์ฒด์˜ ๊ตฌ์กฐ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

1. principal: ์‚ฌ์šฉ์ž ์•„์ด๋”” ํ˜น์€ User๊ฐ์ฒด๋ฅผ ์ €์žฅ 

2. credentials: ์‚ฌ์šฉ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ 

3. authorities: ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ ๋ชฉ๋ก 

4. details: ์ธ์ฆ ๋ถ€๊ฐ€ ์ •๋ณด 

5. Authenticated: ์ธ์ฆ ์—ฌ๋ถ€(Bool)

 

 

1. ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ์‹œ๋„(username + password ์ž…๋ ฅ ๋ฐ ์ „๋‹ฌ)

 

2. usernamePasswordAuthenticationFilter(์ธ์ฆํ•„ํ„ฐ)๊ฐ€ ์š”์ฒญ์ •๋ณด๋ฅผ ๋ฐ›์•„์„œ ์ •๋ณด ์ถ”์ถœ์„ ํ•˜์—ฌ ์ธ์ฆ๊ฐ์ฒด (Authentication)์„ ์ƒ์„ฑํ•œ๋‹ค.

 

3. AuthenticationManager๊ฐ€ ์ธ์ฆ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์ธ์ฆ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. 

 

4. ์ธ์ฆ ์„ฑ๊ณต ํ›„ Authentication ์ธ์ฆ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋‚ด๋ถ€์˜ Principal, Credentials, Authorities, Authenticated ๋“ค์„ ์ฑ„์›Œ๋„ฃ๋Š”๋‹ค.

 

5. SecurityContextHolder๊ฐ์ฒด ์•ˆ์˜ SecurityContext์— ์ €์žฅํ•œ๋‹ค. → ์ธ์ฆ๊ฐ์ฒด๋ฅผ ์ „์—ญ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 

 

์‚ฌ์šฉ์ž ๋ณ„ Authentication ์ธ์ฆ ๊ฐ์ฒด๋Š” ์–ด๋–ป๊ฒŒ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์„๊นŒ??

SecurityContextHolder๋ผ๋Š” ์ „์—ญ ๊ฐ์ฒด ์•ˆ์— SecurityContext์— ์ธ์ฆ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๋Š”๋ฐ, 

 

์ด SecurityContextHolder๋Š” ThreadLocal์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๋ณ„๋กœ ๋‹ค๋ฅธ SecurityContextHolder ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ ์‚ฌ์šฉ์ž ๋ณ„๋กœ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์ธ์ฆ ๊ฐ์ฒด๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

 

 

 

 

 

4. ์ธ์ฆ ์ €์žฅ์†Œ

SecurityContext

Authentication ๊ฐ์ฒด๊ฐ€ ์ €์žฅ๋˜๋Š” ๋ณด๊ด€์†Œ๋กœ ํ•„์š” ์‹œ ์–ธ์ œ๋“ ์ง€ Authentication ๊ฐ์ฒด๋ฅผ ๊บผ๋‚ด์–ด ์“ธ ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณต๋˜๋Š” ํด๋ž˜์Šค์ด๋‹ค. 

 

ThreadLocal์— ์ €์žฅ๋˜์–ด ์•„๋ฌด ๊ณณ์—์„œ๋‚˜ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค๊ณ„๋๊ณ , ๋‹ค๋ฅธ Thread๋กœ ๋ถ€ํ„ฐ ์•ˆ์ „ํ•˜๋‹ค. 

 

 

 

SecurityContextHolder

SecurityContext ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” wrapper ํด๋ž˜์Šค 

SecurityContext๊ฐ์ฒด๋ฅผ ๋ฐ”๋กœ ์ €์žฅํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ณ , ์ €์žฅ ๋ฐฉ์‹(3๊ฐ€์ง€ MODE)์— ๋”ฐ๋ผ ์ €์žฅ์„ ํ•˜๊ณ  ์žˆ๋‹ค.

 

 

  • MODE_THREADLOCAL: ์Šค๋ ˆ๋“œ๋‹น SecurityContext๊ฐ์ฒด๋ฅผ ํ• ๋‹น. default 
  • MODE_INHERITABLETHREADLOCAL: ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์™€ ์ž์‹ ์Šค๋ ˆ๋“œ์— ๊ด€ํ•˜์—ฌ ๋™์ผํ•œ SecurityContext๋ฅผ ์œ ์ง€ → Parent, Child thread์—์„œ ๋™์ผํ•œ SecurityContext๋ฅผ ๊ฐ€์ง„๋‹ค. 
  • MODE_GLOBAL: ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋‹จ ํ•˜๋‚˜์˜ SecurityContext๋ฅผ ์ €์žฅํ•œ๋‹ค. → Memory์—์„œ ๋‹จ ํ•˜๋‚˜์˜ SecurityContext๋ฅผ ๊ฐ€์ง€๊ณ  ์ฐธ์กฐํ•œ๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

 

5. ํผ(Form) ๊ธฐ๋ฐ˜ ๋กœ๊ทธ์ธ

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .formLogin(formLogin -> 
            formLogin
                .loginPage("/login") // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ URL
                .loginProcessingUrl("/loginProc") // ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ URL
                .usernameParameter("userId") // ์‚ฌ์šฉ์ž ์ด๋ฆ„ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„
                .passwordParameter("userPw") // ๋น„๋ฐ€๋ฒˆํ˜ธ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„
                .defaultSuccessUrl("/main") // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ ์ด๋™ํ•  URL
                .failureHandler(customAuthenticationFailureHandler) // ๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ ์ฒ˜๋ฆฌ
                .permitAll() // ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ "/login" ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์ ‘๊ทผ ํ—ˆ์šฉ
        );

    return http.build();
}

 

Spring Security๊ฐ€ ์‚ฌ์šฉํ•  ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋ฅผ ์ง€์ •ํ•˜๊ณ , loginProcessingUrl() ํ•จ์ˆ˜์— ์ง€์ •๋œ URL๋กœ ๋กœ๊ทธ์ธ ์š”์ฒญ์ด ์ „์†ก๋˜๋ฉด Spring Security๊ฐ€ usernameParameter(), passwordParameter()์— ์„ค์ •๋œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

 

 

 

ํ”Œ๋กœ์šฐ

1. ๋กœ๊ทธ์ธ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด UsernamePasswordAuthenticationFilter๋Š” HttpServletRequest ์—์„œ ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ถ”์ถœํ•˜์—ฌ UsernamePasswordAuthenticationToken ์ด๋ผ๋Š” ์ธ์ฆ ํ† ํฐ์„ ์ƒ์„ฑ

2. ์ƒ์„ฑ๋œ ํ† ํฐ์€ AuthenticationManager์—๊ฒŒ ์ „๋‹ฌ

3. AUthenticationManager๋Š” ์ „๋‹ฌ๋ฐ›์€ ํ† ํฐ์„ AuthenticationProvicer์—๊ฒŒ ์ „๋‹ฌ

4. UserDetailsService๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธ ์š”์ฒญ์ž์˜ ์ •๋ณด์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋น„๊ตํ•œ ํ›„, ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์ด๋ฅผ AuthenticationProvicer์—๊ฒŒ ๋ฐ˜ํ™˜

5. AuthenticationProvicer๋Š” ์ „๋‹ฌ๋ฐ›์€ ์‚ฌ์šฉ์ž ์ •๋ณด์—์„œ ํŒจ์Šค์›Œ๋“œ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜์—ฌ, ํŒจ์Šค์›Œ๋“œ ๋น„๊ต. ์ผ์น˜ํ•  ๊ฒฝ์šฐ ์ธ์ฆ ํ† ํฐ์„ ์ƒ์„ฑํ•˜์—ฌ AuthenticationManager์—๊ฒŒ ๋ฐ˜ํ™˜

6. AuthenticationManager๋Š” ์‚ฌ์šฉ์ž ์ธ์ฆ ๊ฐ์ฒด๋ฅผ SecurityContextHolder์— ์ €์žฅ

7, 8. ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ

 

 

 

 

 

 

 

 

 

 

 

6. JWT ๊ธฐ๋ฐ˜ ๋กœ๊ทธ์ธ

JWT ๋ž€?

JWT๋Š” Header, Payload, Signature 3๊ฐ€์ง€ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

 

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

 

Payload๋Š” Claims๋ผ๋Š” ์ •๋ณด๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ํด๋ ˆ์ž„์€ ์‚ฌ์šฉ์ž์™€ ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ๋“ค์ด๋‚˜ ์ถ”๊ฐ€ ์ •๋ณด๋“ค์˜ ์ƒํƒœ๋ฅผ ๋œปํ•œ๋‹ค. ํด๋ ˆ์ž„์—๋Š” Registered, Public, Private 3๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

 

  • Registered ํด๋ ˆ์ž„์€ ๋ฏธ๋ฆฌ ์ •์˜๋œ ํด๋ ˆ์ž„ ์„ธํŠธ์ด๋‹ค. JWT ๋ฐœ๊ธ‰์ž, ํ† ํฐ ์ œ๋ชฉ, ํ† ํฐ ๋งŒ๋ฃŒ ์‹œ๊ฐ„, ํ† ํฐ ํ™œ์„ฑ ๋‚ ์งœ, ํ† ํฐ ๋ฐœ๊ธ‰ ์‹œ๊ฐ„, JWT ๊ณ ์œ  ์‹๋ณ„์ž ๋“ฑ, ๋‹ค์–‘ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜๋Š” ํด๋ ˆ์ž„์ด๋‹ค.
  • Public ํด๋ ˆ์ž„์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ ˆ์ž„์ด๋‹ค.์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ •์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ํด๋ ˆ์ž„์—์„œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ Public ํด๋ ˆ์ž„์˜ ์ด๋ฆ„์€ ๋ณดํ†ต URI๋กœ ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.
  • Private ํด๋ ˆ์ž„๋„ ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ ˆ์ž„์ด๋‹ค. ํ†ต์‹  ๋‹น์‚ฌ์ž ๊ฐ„์˜ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ํด๋ ˆ์ž„์œผ๋กœ ๊ณต๊ฐœ๋˜์–ด๋„ ์ƒ๊ด€์—†๋Š” '์‚ฌ์šฉ์ž๋ฅผ ํŠน์ •ํ•  ์ˆ˜ ์žˆ๋Š”' ์ •๋ณด๋ฅผ ๋‹ด๋Š”๋‹ค.

 

Signature๋Š” ํ† ํฐ์— ํฌํ•จ๋œ ์ •๋ณด๋“ค์ด ํ†ต์‹  ๊ณผ์ •์—์„œ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ๊ฒ€์ฆํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค. Signature๋Š” Header์™€ Payload๋ฅผ Base64-URL๋กœ ์ธ์ฝ”๋”ฉํ•œ ๋ฌธ์ž์—ด๋“ค๊ณผ Secret Key๋ฅผ ํฌํ•จํ•ด HMAC SHA256 ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ์•”ํ˜ธํ™”ํ•œ๋‹ค. 

 

๋นจ๊ฐ„์ƒ‰์€ Header, ๋ณด๋ฝ์ƒ‰์€ Payload, ํŒŒ๋ž€์ƒ‰์€ Signature์ด๋‹ค.

 

 

 

 

ํ”Œ๋กœ์šฐ 

JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•œ ์ธ์ฆ, ์ธ๊ฐ€ ํ”„๋กœ์„ธ์Šค๋Š” ๋Œ€๋žต์ ์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.


 

 

 

์œ„ ํ”„๋กœ์„ธ์Šค์— ํ•ด๋‹นํ•˜๋Š” ๋กœ์ง์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„๋œ๋‹ค. ์„ธ๋ถ€์ ์ธ ์ฝ”๋“œ๋“ค์€ ์ƒ๋žตํ–ˆ์ง€๋งŒ, ํ๋ฆ„์„ ํŒŒ์•…ํ•˜๊ธฐ์—” ์ถฉ๋ถ„ํ•  ๊ฒƒ์ด๋‹ค. 

@RequiredArgsConstructor
@Component
public class JwtFilter extends OncePerRequestFilter {

    private final JwtProvier jwtProvider;
    private final CustomUserDetailsService customUserDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
        FilterChain filterChain) throws ServletException, IOException {

        String token = extractToken(request);

        if (token != null && jwtProvider.validateToken(token)) {
            setAuthentication(token);
        }

        filterChain.doFilter(request, response);
    }

    private String extractToken(HttpServletRequest request) {
        String authHeader = request.getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7);
        }
        return null;
    }

    private void setAuthentication(String token) {
        Long memberId = jwtProvider.getMemberId(token);
        UserDetails userDetails = customUserDetailsService.loadUserByUsername(memberId.toString());

        UsernamePasswordAuthenticationToken authentication =
            new UsernamePasswordAuthenticationToken(userDetails, null,
                userDetails.getAuthorities());

        SecurityContextHolder.getContext().setAuthentication(authentication);
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

(์ฐธ๊ณ ) ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ํšŒ์› & RBAC ๊ด€๋ฆฌ

๋กœ๊ทธ์ธํ•œ ํšŒ์›์„ ๊ฐ€์ ธ์˜ค๋Š” 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•

1. SecurityUtils ์‚ฌ์šฉ

public class SecurityUtils {

    public static LoginMember getLoginMember() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() instanceof UserDetails) {
            LoginMember loginMember = (LoginMember) authentication.getPrincipal();
            return loginMember;
        }
        return null;
    }
}

 

 

 

2. @AuthenticationPrincipal ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ

public class UserController {
    @GetMapping("/current-user")
    public String getCurrentUser(@AuthenticationPrincipal LoginMember loginMember) {
        return userDetails.getUsername();
    }
}

 

 

 

3. ArgumentResolver ๋“ฑ๋ก

@AuthenticationPrincipal ์–ด๋…ธํ…Œ์ด์…˜์€ ๋„ˆ๋ฌด ๊ธธ๋‹ค๋ฉด ArgumentResolver๋ฅผ ๋ณ„๋„๋กœ ๋“ฑ๋กํ•ด์„œ ์‚ฌ์šฉํ•ด๋„ ์ข‹๋‹ค. 

@Component
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(LoginMember.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        return SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }
}
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

    private final LoginMemberArgumentResolver loginMemberArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(loginMemberArgumentResolver);
    }
}

 

public class UserController {
    @GetMapping("/current-user")
    public String getCurrentUser(LoginMember loginMember) {
        return userDetails.getUsername();
    }
}

 

 

๋ญ˜ ์‚ฌ์šฉํ•ด๋„ ์ƒ๊ด€์—†์ง€๋งŒ ๋‚œ ๊ฐœ์ธ์ ์œผ๋กœ 3๋ฒˆ์ด ๊ฐ€์žฅ ๋ง˜์— ๋“ ๋‹ค. 

 

 

 

 

 

 

RBAC์„ ๊ด€๋ฆฌํ•˜๋Š” 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•

1. http.authorizeHttpRequests()

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        // ... //

        http.authorizeHttpRequests(authorize -> authorize
            .antMatchers("/admin/**").hasRole("ADMIN") // ๊ด€๋ฆฌ์ž๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
            .antMatchers("/manager/**").hasAnyRole("ADMIN", "MANAGER") // ๊ด€๋ฆฌ์ž์™€ ๋งค๋‹ˆ์ € ์ ‘๊ทผ ๊ฐ€๋Šฅ
            .antMatchers("/user/**").hasRole("USER") // ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
            .antMatchers("/public/**").permitAll() // ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ ‘๊ทผ ๊ฐ€๋Šฅ
            .anyRequest().authenticated() // ๊ทธ ์™ธ ์š”์ฒญ์€ ์ธ์ฆ ํ•„์š”
        );

        return http.build();
    }

 

 

 

 

2. ๋ฉ”์„œ๋“œ ๊ธฐ๋ฐ˜ RBAC ์„ค์ •

@Service
public class UserService {

    @PreAuthorize("hasRole('ADMIN')") // ADMIN๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
    public void adminOnlyMethod() {
        System.out.println("Admin only method");
    }

    @PreAuthorize("hasAnyRole('ADMIN', 'USER')")
    public void adminOrManagerMethod() {
        System.out.println("Admin or Manager method");
    }

    @PreAuthorize("hasRole('USER')") // USER๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
    public void userOnlyMethod() {
        System.out.println("User only method");
    }
}

 

 

1๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ /* ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํŒจํ„ด์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ํœด๋จผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฝ๋‹ค. ๋˜ํ•œ ํŠน์ • ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋ณด๊ณ  ํ•„์š”ํ•œ ๊ถŒํ•œ์„ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด์„  SecurityConfig์— ๋“ค์–ด๊ฐ€ ์ง์ ‘ ์ฐพ์•„๋ด์•ผ ํ•œ๋‹ค. 

 

๊ทธ๋ž˜์„œ ๋‚˜๋Š” ๊ฐœ์ธ์ ์œผ๋กœ 2๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ๋” ์„ ํ˜ธํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด custom annotaion์„ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.