์นด์นด์˜ค ๋กœ๊ทธ์ธ ๋™์˜ ํ•ญ๋ชฉ ๋ฌธ์ œ ํ•ด๊ฒฐ
ยท
ํ”„๋กœ์ ํŠธ/NolGoat
๋ฌธ์ œ ๊ฐœ์š”ํ˜„์žฌ ์ €ํฌ ์„œ๋น„์Šค์—์„œ๋Š” ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์‹œ, `๋‹‰๋„ค์ž„`์€ ํ•„์ˆ˜ ํ•ญ๋ชฉ, `ํ”„๋กœํ•„ ์‚ฌ์ง„`์€ ์„ ํƒ ํ•ญ๋ชฉ์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋กœ๊ทธ์•„์›ƒ ํ›„ ๋‹ค์‹œ ๋กœ๊ทธ์ธ์„ ์ง„ํ–‰ํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด `ํ”„๋กœํ•„ ์‚ฌ์ง„`์ด ํ•„์ˆ˜ ํ•ญ๋ชฉ์œผ๋กœ ๋ฐ”๋€Œ์–ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ฐ•์ œ๋กœ ์„ ํƒํ•˜๋„๋ก ์š”๊ตฌ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์›์ธ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด๋Š” OAuth2 ๋กœ๊ทธ์ธ ์„ค์ • ํŒŒ์ผ(`.yml`)์˜ `scope` ์˜ต์…˜ ์„ค์ • ๋•Œ๋ฌธ์ด์—ˆ๋Š”๋ฐ, ์ฒ˜์Œ์—๋Š” `scope` ํ•ญ๋ชฉ์ด ๋‹จ์ˆœํžˆ ์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ์„ ์œ„ํ•ด ํ•„์š”ํ•œ ์„ค์ •์œผ๋กœ๋งŒ ์ƒ๊ฐํ•˜์—ฌ ์ž˜๋ชป ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.ํ•˜์ง€๋งŒ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•ด ๋ณด๋ฉด, `scope` ์˜ต์…˜์€ `์ถ”๊ฐ€ ํ•ญ๋ชฉ ๋™์˜ ๋ฐ›๊ธฐ` ์š”์ฒญ ์‹œ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ์˜ต์…˜์— ์„ค์ •๋œ ํ•ญ๋ชฉ์ด ์žˆ์œผ๋ฉด ๋กœ๊ทธ์ธํ•  ๋•Œ๋งˆ๋‹ค ์‚ฌ์šฉ์ž ๋™์˜๋ฅผ ๋‹ค์‹œ ์œ ๋„ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ž˜..
๋ณด์•ˆ ์ทจ์•ฝ์  ํ•ด๊ฒฐ์„ ์œ„ํ•œ AWS S3 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ณ€๊ฒฝ
ยท
ํ”„๋กœ์ ํŠธ/NolGoat
๋ฌธ์ œ ๊ฐœ์š”ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ ์‹œ, ์ง€์†์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€์˜ ์›์ธ์„ ํ™•์ธํ•œ ๊ฒฐ๊ณผ, ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ `org.springframework.cloud:spring-cloud-starter-aws` ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋ณด์•ˆ ์ทจ์•ฝ์ ์œผ๋กœ ์ธํ•ด 2021๋…„ 2์›” ์ดํ›„ Maven Repository์—์„œ ๋” ์ด์ƒ ์—…๋ฐ์ดํŠธ๋ฅผ ์ง€์›์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.`build.gradle`์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์˜์กด์„ฑ์— ์ทจ์•ฝ์ ์ด ์žˆ๋‹ค๋Š” ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ณ€๊ฒฝํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด `org.springframework.cloud:spring-cloud-starter-aws` ๋Œ€์‹  `io.awspring.cloud:spring-cloud-aws-starter-s3:3.0.0` ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ณ€๊ฒฝํ–ˆ์Šต..
์†Œ์…œ ๋กœ๊ทธ์ธ ํšŒ์› ํƒˆํ‡ด ๊ตฌํ˜„
ยท
ํ”„๋กœ์ ํŠธ/NolGoat
๊ฐœ์š”๊ธฐ์กด ํšŒ์› ํƒˆํ‡ด ๋ฐฉ์‹์€ ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํšŒ์› ์ •๋ณด๋ฅผ ์‚ญ์ œํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•๋งŒ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณด๋‹ค ํ™•์‹คํ•œ ํƒˆํ‡ด ์ง„ํ–‰์„ ์œ„ํ•ด, ์†Œ์…œ ๋กœ๊ทธ์ธ ์ œ๊ณต์ž(`Google`, `Kakao`)์™€์˜ ๊ณ„์ • ์—ฐ๊ฒฐ ํ•ด์ œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ณ„์ • ์—ฐ๊ฒฐ ํ•ด์ œ ์š”์ฒญGoogle Google Developers - revoke ์—์„œ ์—ฐ๊ฒฐ ํ•ด์ œ ๋ฐฉ๋ฒ•์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โ€‹Kakao Kakao Developers - unlink ์—์„œ ์—ฐ๊ฒฐ ํ•ด์ œ ๋ฐฉ๋ฒ•์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.Access ํ† ํฐ ๋˜๋Š” ์•ฑ ์–ด๋“œ๋ฏผ ํ‚ค(`Admin key`)๋กœ ์—ฐ๊ฒฐ ํ•ด์ œ API๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ ๋Š๊ธฐ ์š”์ฒญ์— ์„ฑ๊ณตํ•˜๋ฉด ํ•ด๋‹น ์‚ฌ์šฉ์ž ํšŒ์› ๋ฒˆํ˜ธ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ฐ›๊ณ , ๋กœ๊ทธ์•„์›ƒ์ด ํ•จ๊ป˜ ์ง„ํ–‰๋˜์–ด Access ํ† ํฐ๊ณผ Refresh ํ† ํฐ์ด ๋งŒ๋ฃŒ..
ํšจ์œจ์ ์ธ ํ† ํฐ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Redis ๋„์ž…
ยท
ํ”„๋กœ์ ํŠธ/NolGoat
๊ฐœ์š”ํ˜„์žฌ, `Refresh` ํ† ํฐ์€ `MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค`์—์„œ ๊ด€๋ฆฌ๋˜์ง€๋งŒ, `Access` ํ† ํฐ์€ ๋ณ„๋„์˜ ์ €์žฅ์†Œ ์—†์ด ํด๋ผ์ด์–ธํŠธ `๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€`์—์„œ๋งŒ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.๋ฌธ์ œ์ ๋กœ๊ทธ์•„์›ƒ ์‹œ, Access ํ† ํฐ ์ฒ˜๋ฆฌ ๋ฌธ์ œRefresh ํ† ํฐ์€ ๋กœ๊ทธ์•„์›ƒ ์‹œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์‚ญ์ œํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์กด์žฌ ์—ฌ๋ถ€๋กœ ์œ ํšจํ•œ ํ† ํฐ์ธ์ง€ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, Access ํ† ํฐ์€ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์‚ญ์ œ๋  ๋ฟ, ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ์ „๊นŒ์ง€๋Š” ์—ฌ์ „ํžˆ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.์„ฑ๋Šฅ ๋ฌธ์ œ๋งŒ์•ฝ Access ํ† ํฐ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋“ฑ๋กํ•˜์—ฌ ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค ํ•ด๋„, ์š”์ฒญ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์กฐํšŒํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.ํ† ํฐ ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ๊ด€๋ฆฌ ๋ฌธ์ œํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ๋„ ์‚ญ์ œํ•ด ์ค˜์•ผ ํ•˜๋Š”๋ฐ, ์ด๋ฅผ ์œ„ํ•ด ๋ณ„๋„์˜ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.์„ฑ๋Šฅ๊ณผ ํ† ํฐ..
์ธ์ฆ ๋ณด์•ˆ ๊ฐ•ํ™”
ยท
ํ”„๋กœ์ ํŠธ/NolGoat
๊ฐœ์š”ํ˜„์žฌ `Access` ํ† ํฐ์€ `๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€`์—, `Refresh` ํ† ํฐ์€ `์ฟ ํ‚ค`์— ์ €์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ตฌ์กฐ์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” `XSS` ๋ฐ `CSRF` ๊ณต๊ฒฉ์— ์˜ํ•œ ํ”ผํ•ด๋ฅผ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ฏผํ•˜๊ณ , ์ ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ฐธ๊ณ ) XSS์™€ CSRF ๊ณต๊ฒฉXSS (Cross-Site Scripting) ๊ณต๊ฒฉ์•…์„ฑ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•ด ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์—์„œ ํ† ํฐ์„ ํƒˆ์ทจํ•˜๋Š” ๊ณต๊ฒฉ์ž…๋‹ˆ๋‹ค.์ด๋ฅผ ๋ฐฉ์–ดํ•˜๊ธฐ ์œ„ํ•ด `Http-Only` ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.Http-Only ์ฟ ํ‚ค๋Š” ์Šคํฌ๋ฆฝํŠธ์˜ ์ ‘๊ทผ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค.CSRF (Cross-Site Request Forgery) ๊ณต๊ฒฉ๊ณต๊ฒฉ์ž๊ฐ€ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋ฅผ ์œ ๋„ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์˜๋„ํ•˜์ง€ ์•Š์€ ์š”์ฒญ์„ ์„œ๋ฒ„์— ๋ณด๋‚ด๋„๋ก ๋งŒ๋“œ๋Š” ๊ณต๊ฒฉ์ž…๋‹ˆ๋‹ค.๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ๋œ ํ† ํฐ์€ ํด๋ผ..
์ธ์ฆ์ด ํ•„์š”ํ•œ URL ๊ณตํ†ต ๊ด€๋ฆฌ
ยท
ํ”„๋กœ์ ํŠธ/NolGoat
๋ฌธ์ œ ๊ฐœ์š”ํ˜„์žฌ, ์ธ์ฆ์ด ํ•„์š”ํ•œ URL ๋ชฉ๋ก์€ `AuthFilter`์™€ `SecurityConfig`์—์„œ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.AuthFilter์—์„œ๋Š” ์–ด๋–ค ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ, ์ธ์ฆ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ Access ํ† ํฐ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, ์ธ์ฆ์ด ํ•„์š”ํ•œ URL ๋ชฉ๋ก์„ ํ†ตํ•ด ํ•„ํ„ฐ๋งํ•˜์ง€ ์•Š์œผ๋ฉด, ์ธ์ฆ์ด ํ•„์š” ์—†๋Š” ์š”์ฒญ๊นŒ์ง€ Access ํ† ํฐ์„ ๊ฒ€์ฆํ•˜์—ฌ ์ธ์ฆ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด URL ํ†ต๊ณผ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.@Overrideprotected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { return super.shouldNotFilter(request);} SecurityC..