JiwonDev

Spring Security #2 ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ๋ฒ• - ์ต๋ช…์‚ฌ์šฉ์ž, ์„ธ์…˜ ์ œ์–ด, ์˜ˆ์™ธ์ฒ˜๋ฆฌ

by JiwonDev

 

 

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ - Spring Boot ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœํ•˜๋Š” Spring Security - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

์ดˆ๊ธ‰์—์„œ ์ค‘.๊ณ ๊ธ‰์— ์ด๋ฅด๊ธฐ๊นŒ์ง€ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๋ถ€ํ„ฐ API ์‚ฌ์šฉ๋ฒ•๊ณผ ๋‚ด๋ถ€ ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ•™์Šตํ•˜๊ฒŒ ๋˜๊ณ  ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์‹ค์ „ ํ”„๋กœ์ ํŠธ๋ฅผ ์™„์„ฑํ•ด ๋‚˜๊ฐ์œผ๋กœ์จ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์˜ ์ธ์ฆ๊ณผ

www.inflearn.com

 

์•„๋ž˜์˜ ๋ณด์•ˆ ๊ธฐ๋Šฅ๋“ค์€ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ณ ์žํ•˜๋ฉด ์ƒ๋‹นํžˆ ๊ท€์ฐฎ๋‹ค.

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—์„œ๋Š” ๊ฐ„๋‹จํ•œ ์„ค์ • ๊ฐ’์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ’ญ ์ต๋ช… ์‚ฌ์šฉ์ž ํ•„ํ„ฐ (AnonymousAuthenticationFilter)

์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ํ˜„์žฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ(๋กœ๊ทธ์ธ)์ด ๋˜์–ด์žˆ๋Š”์ง€, ์•„๋‹Œ์ง€๋ฅผ ํŒ๋‹จํ•˜๋Š” ํ•„ํ„ฐ์ด๋‹ค.

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

์ธ์ฆ๊ฐ์ฒด๊ฐ€ null์ด๋ผ๋ฉด SecurityContext๋งŒ์œผ๋กœ๋Š” ์ต๋ช…์‚ฌ์šฉ์ž๊ฐ€ ์žˆ๋Š”์ง€, ์•„์˜ˆ ์ ‘์†์„ ํ•˜์ง€ ์•Š์€๊ฑด์ง€ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์—†๋‹ค.

์ต๋ช…์‚ฌ์šฉ์ž ํ† ํฐ์„ ํ†ตํ•ด ์ธ์ฆ ์—ฌ๋ถ€์— ๋”ฐ๋ฅธ ๋‹ค๋ฅธ ํ™”๋ฉด์„ ๊ตฌํ˜„ํ•  ๋•Œ, ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

  • isAnonymous() - ์ต๋ช… ์‚ฌ์šฉ์ž์ธ๊ฐ€? (ํŽ˜์ด์ง€์— ๋กœ๊ทธ์ธ ๋ฉ”๋‰ด ํ‘œ์‹œ)
  • isAuthenticated() - ๋กœ๊ทธ์ธ๋œ ์‚ฌ์šฉ์ž์ธ๊ฐ€? (ํŽ˜์ด์ง€ ๋กœ๊ทธ์•„์›ƒ ๋ฉ”๋‰ด ํ‘œ์‹œ)

๋ฌผ๋ก  ์ฒซ ์ ‘์†์—์„œ ์ต๋ช… ์‚ฌ์šฉ์ž ํ† ํฐ(์ธ์ฆ๊ฐ์ฒด)๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋‹ค๋ฉด ์ดํ›„ ๋งŒ๋ฃŒ๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ํ•ด๋‹นํ•„ํ„ฐ๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ธ์ฆ๊ฐ์ฒด๊ฐ€ null์ผ๋•Œ๋งŒ AnonymousAuthenticationFilter๊ฐ€ ๋™์ž‘ํ•œ๋‹ค.

 

 

๐Ÿ’ญ ์„ธ์…˜ ๊ด€๋ฆฌ ํ•„ํ„ฐ (SessionManagementFilter)

๐Ÿ“‘ ๋™์‹œ ์„ธ์…˜ ์ œ์–ด (๋™์ผ๊ณ„์ • ์ค‘๋ณต์ ‘์†)

ํ•œ ๊ณ„์ •์œผ๋กœ ์—ฌ๋Ÿฌ ์ปดํ“จํ„ฐ์—์„œ ์ ‘์†ํ•˜๋Š” ๊ฒฝ์šฐ, ์„ธ์…˜์€ ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—์„œ๋Š” http.sessionManagement()๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

maxSessionPreventsLogin(true)๋ฅผ ํ•˜๊ฒŒ๋˜๋ฉด ์•„๋ž˜ ๊ทธ๋ฆผ์˜ [2. ํ˜„์žฌ์‚ฌ์šฉ์ž ์ธ์ฆ์‹คํŒจ] ์ฒ˜๋Ÿผ ๋™์ž‘ํ•œ๋‹ค.

ํ•œ ๊ณ„์ •์œผ๋กœ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์ ‘์†ํ–ˆ์„ ๋•Œ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ์ง€ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. default๊ฐ’์€ [1. ์„ธ์…˜๋งŒ๋ฃŒ]์ด๋‹ค.

 

์ด๋Š” ConcurrentSessionFilter ๋ฅผ ํ†ตํ•ด ๋™์ž‘ํ•˜๊ฒŒ๋œ๋‹ค. ํ•„ํ„ฐ์˜ ๋™์ž‘์€ ์•ž ๊ธ€์—์„œ ๋งŽ์ด ๋‹ค๋ค˜์œผ๋ฏ€๋กœ, ๊ถ๊ธˆํ•˜๋ฉด ๊ตฌ๊ธ€ ๊ฒ€์ƒ‰ํ•˜์ž

2021.11.22 - [๐ŸŒฑBackend/Spring Security] - Spring Security #1 ๊ธฐ๋ณธ๋™์ž‘ ์ดํ•ดํ•˜๊ธฐ

 

 

 

๐Ÿ“‘ ์„ธ์…˜ ๊ณ ์ • ๋ณดํ˜ธ (์„ธ์…˜ ์ฃผ์ž… ๊ณต๊ฒฉ, sessionFixation)

๋ณดํ†ต ์›น ์„œ๋น„์Šค๋Š” ๋กœ๊ทธ์•„์›ƒ ํ›„ ๋ฐ”๋กœ ๋‹ค์‹œ ๋กœ๊ทธ์ธ์„ ํ•˜๋”๋ผ๋„ ๊ธฐ์กด์˜ JSESSIONID๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ ๋ฐœ๊ธ‰ํ•œ๋‹ค.

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์„ธ์…˜์— ๊ธฐ์กด์˜ ์ธ์ฆ๊ฐœ์ฒด๊ฐ€ ์žˆ๋”๋ผ๋„ ๋กœ๊ทธ์ธ์„ ์š”์ฒญํ•˜๋ฉด JSESSIONID๋Š” ์ƒˆ๋กœ ๋ฐœ๊ธ‰ํ•œ๋‹ค. 

๊ธฐ์กด์˜ ๊ฐ’์„ ์ด์šฉํ•ด๋„ ๋ ๊ฑฐ๊ฐ™์€๋ฐ, ๋ฒˆ๊ฑฐ๋กญ๊ฒŒ ๋กœ๊ทธ์ธ ์š”์ฒญ๋งˆ๋‹ค ์ƒˆ๋กญ๊ฒŒ ๋ฐœ๊ธ‰ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ผ๊นŒ?

 

์ด๋Š” ์„ธ์…˜๊ณ ์ •๊ณต๊ฒฉ (SessionFixation)์œผ๋กœ ์ธํ•œ ์„ธ์…˜ ํ•˜์ด์žฌํ‚น(์„ธ์…˜ ํƒˆ์ทจ)๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•จ์ด๋‹ค.

๋งŒ์•ฝ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ณต๊ฒฉ์ž๊ฐ€ ๋จผ์ € ๋กœ๊ทธ์ธ์„ ํ•œ ํ›„, ์‚ฌ์šฉ์ž ์ปดํ“จํ„ฐ์— JSESSIONID ์ฟ ํ‚ค๋ฅผ ์‹ฌ์–ด๋†“์•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž. 

<!-- script ๋ฅผ ์ด์šฉํ•œ ์„ธ์…˜ ์ฃผ์ž… -->
<script>document.cookie="jsessionid=ํ•จ์ •์„ธ์…˜ID";</script>

<!-- meta ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•œ ์„ธ์…˜ ์ฃผ์ž… -->
<meta http-equiv="Set-Cookie" content="jsessionid=ํ•จ์ •์„ธ์…˜ID">

์ด๋ฅผ ์„ธ์…˜ ๊ณ ์ • ๊ณต๊ฒฉ์„ ํ†ตํ•œ ์„ธ์…˜ ํ•˜์ด์žฌํ‚น์ด๋ผ๊ณ  ํ•œ๋‹ค.

์ด๋ฅผ ์„ธ์…˜ ๊ณ ์ • ๊ณต๊ฒฉ์ด๋ผ๊ณ  ํ•œ๋‹ค.

๋‹น์—ฐํžˆ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—์„œ๋Š” ์„ธ์…˜๊ณ ์ •๋ณดํ˜ธ(changeSessionId)๊ฐ€ ๊ธฐ๋ณธ์ ์šฉ๋˜์–ด์žˆ์œผ๋ฉฐ, ์ด๋Š” ์„ค์ •์—์„œ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

newSession()์€ ์ด์ „ ์„ธ์…˜์—์„œ ์„ค์ •ํ•œ ์ธ์ฆ๊ฐœ์ฒด์˜ ์†์„ฑ ๊ฐ’๋„ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค. (์ธ์ฆ๊ฐœ์ฒด clear)

 

๋ฌผ๋ก  ์ด๋ฅผ ๋ณ€๊ฒฝ ํ•  ์ผ์€ ๊ฑฐ์˜ ์—†๋‹ค. ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ์•Œ๊ณ ๋Š” ์žˆ๋„๋ก ํ•˜์ž.

๐Ÿ˜’ : ์›๋ž˜ ์›น์€ JSESSIONID๋ฅผ ๋งค๋ฒˆ ์ƒˆ๋กญ๊ฒŒ ๋ฐœ๊ธ‰ํ•ด์ฃผ๋Š”๊ฑด๊ฐ€์š”?
๐Ÿ™„ : ์–ด...์ž˜๋ชจ๋ฅด๊ฒ ๋Š”๋ฐ ๋Œ๋ ค๋ณด๋‹ˆ๊นŒ ๊ทธ๋ ‡๋”๋ผ๊ตฌ์š”. ์•„๋งˆ ๊ทธ๋ ‡์ง€ ์•Š์„๊นŒ์š”? (???)

 

 

๐Ÿ“‘ ์„ธ์…˜ ์ •์ฑ… ๋ณ€๊ฒฝ

์›น ์„œ๋น„์Šค์— ๋”ฐ๋ผ ๋”ฐ๋กœ ์‚ฌ์šฉ์ž ์ธ์ฆ์ด ํ•„์š” ์—†๋Š” ๊ฒฝ์šฐ, ์„ธ์…˜์ด ํ•„์š”์—†์„ ์ˆ˜๋„ ์žˆ๋‹ค.

๋˜๋Š” JWTํ† ํฐ ๋“ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋ฒ„์— ์•„์˜ˆ ์„ธ์…˜์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์„ธ์…˜์„ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†๋‹ค.

์ด๋Ÿด ๋•Œ๋Š” ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์˜ ์„ธ์…˜ ์ •์ฑ…(sessionManagement().SessionCreationPolicy)์„ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

Never๋Š” ์ƒ์„ฑ์€ ์•ˆํ•˜์ง€๋งŒ, ์‚ฌ์šฉ์€ ํ•œ๋‹ค. [JWT ํ† ํฐ]์ฒ˜๋Ÿผ ์„ธ์…˜์ด ์•„์˜ˆ ํ•„์š”์—†๋‹ค๋ฉด Stateless๋ฅผ ์‚ฌ์šฉํ•˜์ž.

 

 

๐Ÿ“‘ ์ •๋ฆฌ (SessionManagementFilter)

  • ๊ธฐ๋ณธ์ ์ธ ์„ธ์…˜๊ด€๋ฆฌ
  • ๋™์‹œ์  ์„ธ์…˜ ์ œ์–ด 
  • ์„ธ์…˜ ๊ณ ์ • ๋ณดํ˜ธ (sessionFixation)
  • ์„ธ์…˜ ์ƒ์„ฑ ์ •์ฑ… (Always, If_Required, Never, Stateless)

์ฐธ๊ณ ๋กœ ์ด ๊ณผ์ •์—์„œ๋Š” SessionManagementFilter์™€ ํ•จ๊ป˜ ConcurrentSessionFilter๋„ ์‚ฌ์šฉ๋œ๋‹ค.

 

 

๐Ÿ“‘ ConcurrentSessionFilter, ์ „์ฒด ๋™์ž‘ํ๋ฆ„

ConcurrentSessionFilter๋Š” ๋งค ์š”์ฒญ๋งˆ๋‹ค ํ˜„์žฌ ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜ ๋งŒ๋ฃŒ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๋ฉฐ, ๋งŒ๋ฃŒ์ธ ๊ฒฝ์šฐ ์ฆ‰์‹œ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.

  • ๋กœ๊ทธ์•„์›ƒ์— ํ•„์š”ํ•œ ์ฒ˜๋ฆฌ
  • ์˜ค๋ฅ˜ํŽ˜์ด์ง€ ์‘๋‹ต (ํ•„ํ„ฐ์ฒด์ธ์œผ๋กœ ๋„˜๊ธฐ์ง€ ์•Š๊ณ  ConcurrentSessionFilter ์—์„œ ์ฆ‰์‹œ ์‘๋‹ต)

 

๊ทธ๋ž˜์„œ ์•ž์—์„œ ๋ฐฐ์› ๋˜ UsernamePasswordAuthenticationFilter, SessionManagementFilter์™€ ํ•จ๊ป˜ ๋ณด๋ฉด ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™๋‹ค.

์„ค์ •๊ฐ’์„ ํ†ตํ•ด SessionManagementFilter ์•ˆ์— ์žˆ๋Š” Strategy ์˜ ๊ตฌํ˜„์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿ’ญ ์ธ๊ฐ€ API

์ธ์ฆ(Authentication)์€ '๋‚ด๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€' ํ™•์ธํ•˜๋Š” ์ž‘์—…, ๋กœ๊ทธ์ธ์„ ์˜๋ฏธํ•œ๋‹ค.

์ธ๊ฐ€(Authorization)๋Š” '๋‚ด๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€๋Š” ์•Œ์ง€๋งŒ, ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š”' ์ž‘์—…์ด๋‹ค.

 

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋Š” ์ธ๊ฐ€, ์ฆ‰ ์ ‘๊ทผ ๊ถŒํ•œ ์„ค์ •์„ ์„ ์–ธ์  ๋ฐฉ์‹๊ณผ ๋™์  ๋ฐฉ์‹์œผ๋กœ ์ œ๊ณตํ•ด์ค€๋‹ค.

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋Š” ํŠน์ • ๋ฉ”์„œ๋“œ์—๋„ ์ ‘๊ทผ ๊ถŒํ•œ์„ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿ“‘ ์‚ฌ์šฉ์ž ์ƒ์„ฑ ๋ฐ ๊ถŒํ•œ(Role) ๋ถ€์—ฌ

configure ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ์šฉ ์‚ฌ์šฉ์ž๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    // ๋ฌผ๋ก  ํ…Œ์ŠคํŠธ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜๋Š”๊ฑฐ์ง€, ์‹ค์ œ ์‚ฌ์šฉ์€ ๋™์ ์œผ๋กœ DB์™€ ์—ฐ๋™ํ•ด์„œ ๊ณ„์ •์„ ์ƒ์„ฑํ•œ๋‹ค.
        auth.inMemoryAuthentication().withUser("user").password("{noop}1111").roles("USER");
        auth.inMemoryAuthentication().withUser("system").password("{noop}1111").roles("SYS");
        auth.inMemoryAuthentication().withUser("admin").password("{noop}1111").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() // ์ธ๊ฐ€, ๊ถŒํ•œ์ด ํ•„์š”ํ•œ ์š”์ฒญ URL
            .antMatchers("/user").hasRole("USER") // user๋งŒ ์ ‘๊ทผ๊ฐ€๋Šฅ
            .antMatchers("/admin/pay").hasRole("ADMIN") // admin๋งŒ ์ ‘๊ทผ๊ฐ€๋Šฅ
            .antMatchers("/admin/**").access("hasRole('ADMIN') or hasRole('SYS')") // system,admin๋งŒ
            .anyRequest().authenticated(); // ๊ทธ ์™ธ ๋ชจ๋“  ์š”์ฒญ์€ ์ธ์ฆ๋งŒ ํ•„์š”.

        http.formLogin();
    }
}

URL ์„ค์ •์€ ๊ตฌ์ฒด์ ์ธ ๊ฒฝ๋กœ๋ฅผ ๋จผ์ € ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค.

์ฐธ๊ณ ๋กœ ํฌํ•จ๊ด€๊ณ„ (System์€ Admin๊ณผ User๊ถŒํ•œ์„ ํฌํ•จ)๋ผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("user").password("{noop}1111").roles("USER");
    auth.inMemoryAuthentication().withUser("system").password("{noop}1111").roles("USER","SYS");
    auth.inMemoryAuthentication().withUser("admin").password("{noop}1111").roles("ADMIN","SYS","USER");
}

๋‹ค๋งŒ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—๋Š” ๊ถŒํ•œ ๊ณ„์ธต ๊ธฐ๋Šฅ์ด ์žˆ์–ด์„œ ์ด๋ ‡๊ฒŒ ์ผ์ผ์ด ์ง€์ •ํ•˜์ง€ ์•Š์•„๋„ ํฌํ•จ๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿ“‘ URL ๊ถŒํ•œ ์„ค์ •(์ธ๊ฐ€)

์ฐธ๊ณ ๋กœ ๊ถŒํ•œ ์„ค์ •์„ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

๋ฉ”์†Œ๋“œ  ๋™์ž‘
 authenticated()  ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ์ ‘๊ทผ์„ ํ—ˆ์šฉ
 fullyAuthenticated()  ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ์ ‘๊ทผ์„ ํ—ˆ์šฉ, rememberMe ์ธ์ฆ ์ œ์™ธ
 permitAll()  ๋ฌด์กฐ๊ฑด ์ ‘๊ทผ์„ ํ—ˆ์šฉ (๋ชจ๋‘๊ฐ€ ์ ‘๊ทผ ๊ฐ€๋Šฅ)
 denyAll()  ๋ฌด์กฐ๊ฑด ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Œ
 anonymous()  ์ต๋ช…์‚ฌ์šฉ์ž์˜ ์ ‘๊ทผ์„ ํ—ˆ์šฉ (* ์ฃผ์˜ * ์ธ์ฆ๋œ USER๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Œ)
 rememberMe()  ๊ธฐ์–ตํ•˜๊ธฐ๋ฅผ ํ†ตํ•ด ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ์ ‘๊ทผ์„ ํ—ˆ์šฉ
 access(String)  ์ฃผ์–ด์ง„ SpEL (Spring Exp Lang) ํ‘œํ˜„์‹์˜ ํ‰๊ฐ€ ๊ฒฐ๊ณผ๊ฐ€ true์ด๋ฉด ์ ‘๊ทผ์„ ํ—ˆ์šฉ
 hasRole(String)  ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ์—ญํ• ์ด ์žˆ๋‹ค๋ฉด ์ ‘๊ทผ์„ ํ—ˆ์šฉ (User)
 hasAuthority(String)   ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ๊ถŒํ•œ์ด ์žˆ๋‹ค๋ฉด (Role User)
 hasAnyRole(String...)  ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ๊ถŒํ•œ์ด ์žˆ๋‹ค๋ฉด ์ ‘๊ทผ์„ ํ—ˆ์šฉ
 hasAnyAuthority(String...)  ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ์–ด์ง„ ๊ถŒํ•œ ์ค‘ ์–ด๋–ค ๊ฒƒ์ด๋ผ๋„ ์žˆ๋‹ค๋ฉด ์ ‘๊ทผ์„ ํ—ˆ์šฉ
 hasIpAddress(String)  ์ฃผ์–ด์ง„ IP๋กœ๋ถ€ํ„ฐ ์š”์ฒญ์ด ์™”๋‹ค๋ฉด ์ ‘๊ทผ์„ ํ—ˆ์šฉ

 

 

๐Ÿ’ญ ์ธ์ฆ,์ธ๊ฐ€ ์˜ˆ์™ธ์ฒ˜๋ฆฌ - ExceptionTranslationFilter

์ฐธ๊ณ ๋กœ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์˜ ๋งˆ์ง€๋ง‰ ํ•„ํ„ฐ ์ฒด์ธ์€ ํ•ญ์ƒ FilterSecurityInterceptor ํ•„ํ„ฐ๋กœ ๋๋‚œ๋‹ค.

์ด ํ•„ํ„ฐ ์•ž์— ์œ„์น˜ํ•˜๋Š”๊ฒŒ ExceptionTranslationFilter์ธ๋ฐ, ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ๋ฐ›์„ ๋•Œ

try-catch๋กœ FilterSecurityInterceptor๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋‹ค. ์ฆ‰ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ์—ฌ๊ธฐ์„œ ๋‹ด๋‹นํ•œ๋‹ค.

์ด ํ•„ํ„ฐ ์—ญ์‹œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • AuthenticationException
    1. AuthenticationEntryPoint๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. (๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™, 401 ์˜ค๋ฅ˜์ฝ”๋“œ ์ „๋‹ฌ ๋“ฑ์„ ๋‹ด๋‹น)
    2. ์ธ์ฆ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์ „์˜ ์š”์ฒญ ์ •๋ณด๋ฅผ ์ €์žฅํ•œ๋‹ค.
    โžก RequestCache - ์‚ฌ์šฉ์ž์˜ ์ด์ „ ์š”์ฒญ์ •๋ณด๋ฅผ ์„ธ์…˜์— ์ €์žฅํ•˜๊ณ , ์ด๋ฅผ ๊บผ๋‚ด์˜ค๋Š” ์บ์‹œ ๋ฉ”์ปค๋‹ˆ์ฆ˜
    โžก RequestCache ๋‚ด๋ถ€์˜ SavedRequest ๊ฐ์ฒด - ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ–ˆ๋˜ request ์†์„ฑ, ํ—ค๋”๋“ค์„ ์ €์žฅ.

  • AccessDeniedException
    ์ธ๊ฐ€์— ๊ด€๋ จ๋œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.
    ํŠน๋ณ„ํ•œ ๋™์ž‘์€ ์—†๊ณ  AccessDeniedHandler ์—์„œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋„๋ก ์ œ๊ณตํ•œ๋‹ค.

์ฐธ๊ณ ๋กœ '์ต๋ช…์‚ฌ์šฉ์ž' ๋„ ์ธ์ฆ๊ฐœ์ฒด๊ฐ€ ์กด์žฌํ•˜๊ธฐ๋•Œ๋ฌธ์—, ์ธ์ฆ์˜ˆ์™ธ๊ฐ€ ์•„๋‹ˆ๋ผ ์ธ๊ฐ€์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

RequestCache๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

protected void configure(HttpSecurity http) throws Exception {

    http.exceptionHandling() // ์˜ˆ์™ธ์ฒ˜๋ฆฌ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก (๋žŒ๋‹คํ•จ์ˆ˜ ์‚ฌ์šฉ)
        .authenticationEntryPoint(
            (request, response, authException) -> response.sendRedirect("/login"))
        .accessDeniedHandler(
            (request, response, accessDeniedException) -> response.sendRedirect("/denied"));

    
    http.formLogin()
        .successHandler((request, response, authentication) -> {
            RequestCache requestCache = new HttpSessionRequestCache();
            // ์ธ์ฆ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์ „ ์บ์‹œ๋œ Request ๊ฐ์ฒด
            SavedRequest savedRequest = requestCache.getRequest(request, response);

            String redirectUrl = savedRequest.getRedirectUrl(); // ๊ธฐ์กด์— ๊ฐ€๊ณ ์ž ํ–ˆ๋˜ URL
            response.sendRedirect(redirectUrl);
        });
}

RequestCacheFilter์—์„œ ์ด์ „์˜ Request ๊ฐ์ฒด(savedRequest)๋ฅผ ์„ธ์…˜์— ์บ์‹ฑํ•˜๊ณ  ๋‹ค์Œ ํ•„ํ„ฐ๋กœ ๋„˜๊ธด๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉํ•˜๋Š” ์‹œ์ ์—์„œ request.session์— ์žˆ๋Š” savedRequest๋ฅผ ๊บผ๋‚ธ๋‹ค.

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ