[Spring Security] #2 ์ธ์ฆ ๋ฐฉ์: ์ฟ ํค vs ์ธ์ vs JWT

์ค๋์ ๋ํ์ ์ธ ์ฌ์ฉ์ ์ธ์ฆ ๋ฐฉ์์ธ ์ฟ ํค vs ์ธ์ vs JWT ๋ฐฉ์์ ๋ํด ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
์ ๊ฐ ๋ค์ ๊ฐ์์์๋ ์ธ์ ๊ณผ ์ฟ ํค๋ฅผ ํฉ์ณ ์ค๋ช ํ๋๋ฐ
๋ธ๋ก๊ทธ๋ฅผ ์ฐ๊ธฐ ์ํด ์๋ฃ ์กฐ์ฌ๋ฅผ ํ๋ค๋ณด๋ ์ฟ ํค์ ์ธ์ ์ ๊ตฌ๋ถ์ง๋ ๋ถ๋ค์ด ๋ง์ผ์๋๋ผ๊ณ ์.
์ถ๊ฐ์ ์ผ๋ก ํ์ตํ ๋ด์ฉ์ ์ข ํฉํ์ฌ ์จ๋ด ๋๋ค.
๋จผ์ ์ฝ์ผ๋ฉด ์ข์ ๊ธ: ์ธ์ฆ๊ณผ ์ธ๊ฐ ๊ฐ๋ https://syleeblog.tistory.com/40
๐ช ์ฟ ํค ๋ฐฉ์
์น์์ ์ฟ ํค๋ ์๋ฒ๊ฐ ์ฌ์ฉ์์ ์น ๋ธ๋ผ์ฐ์ ์ ์ ์กํ๋ ์์ ๋ฐ์ดํฐ ์กฐ๊ฐ์ ๋๋ค.
๋ธ๋ผ์ฐ์ ๋ ๋ฐ์ดํฐ ์กฐ๊ฐ๋ค์ ์ ์ฅํด ๋์๋ค๊ฐ, ๋์ผํ ์๋ฒ์ ์ฌ ์์ฒญ ์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ํจ๊ฒ ์ ์กํฉ๋๋ค.
์ถ์ฒ: MDN WEB DOCS

1. ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์ ๋ก๊ทธ์ธ ์ธ์ฆ ์์ฒญ์ ๋ณด๋ ๋๋ค.
2. ์๋ฒ์์๋ ์ ํฉํ ์ ์ ์ธ์ง ์ธ์ฆํฉ๋๋ค.
3. ์ธ์ฆ์ด ์๋ฃ๋๋ฉด ์ฟ ํค์ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด(์ ์ ID๋ ์ธ๋ฑ์ค ๋ฑ ์ด ์ ์ ๋ฅผ ์ธ์ฆํ ์ ๋ณด/์๋ณํ๊ธฐ ์ํ ์ ๋ณด)๋ฅผ ๋ด์ ์๋ตํฉ๋๋ค.
4. ํด๋ผ์ด์ธํธ ์ฟ ํค์ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๊ฐ ์ ์ฅ๋์ต๋๋ค.
5. ํด๋ผ์ด์ธํธ๊ฐ ์ฌ์์ฒญ์ ํ ๋๋ง๋ค ์ฟ ํค์๋ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๊ฐ ๋ด๊ฒจ ์์ต๋๋ค. ์๋ฒ๋ ์ด๋ฅผ ํ ๋๋ก ์ธ๊ฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
์ฌ์ฉ์์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์๋ฒ๊ฐ ์ ์ฅํ์ง ์๊ณ , ํด๋ผ์ด์ธํธ๊ฐ ์ ์ฅํ ํ ์์ฒญ๋ง๋ค ์ธ์ฆ ์ ๋ณด๋ฅผ ์ฟ ํค์ ๋ด์ ๋ณด๋ด๋ ๋ฐฉ์์ ๋๋ค.
์ด๋ ๊ฒ ์๋ฒ๊ฐ ์ธ์ฆ ์ํ๋ฅผ ๊ด๋ฆฌํ์ง ์๋ ๊ฒ์ "Stateless(๋ฌด์ํ)"ํ๋ค๊ณ ํํํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ด๋ ๊ฒ ๋จ์ํ ์ฟ ํค ๋ฐฉ์์ ์ ์ฌ์ฉ๋์ง ์์ต๋๋ค. ํด๋ผ์ด์ธํธ์์ ์ฟ ํค์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ฝ๊ฒ ์์กฐํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
๐๏ธ ์ธ์ ๋ฐฉ์
์ธ์ ์ ๋ธ๋ผ์ฐ์ (ํด๋ผ์ด์ธํธ)์ ์น ์๋ฒ๊ฐ ์ฐ๊ฒฐ๋์ด ๋ธ๋ผ์ฐ์ ๊ฐ ์ข ๋ฃ๋ ๋๊น์ง์ ์์ ์ ๋งํฉ๋๋ค.
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ ํ ๋
์ฌ๋ฐ๋ฅธ ์ฌ์ฉ์์์ด ์ธ์ฆ๋๋ฉด ์๋ฒ๋ ์ฟ ํค์ ์ธ์ ID๋ฅผ ๋ด์ ์๋ตํฉ๋๋ค.
์ดํ ํด๋ผ์ด์ธํธ๋ ์์ฒญ ์ ์ฟ ํค์ ์ ์ฅ๋ ์ธ์ ID๋ฅผ ํจ๊ป ์ ๋ฌํ์ฌ ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ๋ฅผ ์๋ณํ ์ ์๋๋ก ํฉ๋๋ค.
1. ํด๋ผ์ด์ธํธ์์ ๋ก๊ทธ์ธ์ ์์ฒญํฉ๋๋ค.
2. ์๋ฒ์์ ์ฌ์ฉ์ ์๋ณ ํ ์๋ฒ์ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ์ ์ฅํฉ๋๋ค.
3. ์ฟ ํค์ ์ธ์ ID๋ฅผ ๋ด์ ์๋ตํฉ๋๋ค.
4. ํด๋ผ์ด์ธํธ๊ฐ ์ธ์ ID๋ฅผ ๊ฐ์ง๊ณ ์๋ก์ด ์ธ๊ฐ ์์ฒญ์ ํฉ๋๋ค.
5. ์๋ฒ์์๋ ์ธ์ ID๋ฅผ ๋ฐํ์ผ๋ก ์๋ฒ์ ์ ์ฅ๋ ์ธ์ฆ ์ ๋ณด๋ฅผ ํ์ธ ํ ์ธ๊ฐ ์ฒ๋ฆฌ๋ฅผ ํฉ๋๋ค.
์๋ ์ฝ๋์์ session.setAttribute๋ก ์ธ์ ์ ๋ณด๋ฅผ ์ ์ฅํ ์ ์์ต๋๋ค.
@PostMapping("/login")
public ResponseEntity<?> login(LoginDto dto,
HttpSession session) {
User u = service.verify(dto.email(), dto.password());
session.setAttribute("LOGIN_ID", u.id());
return ResponseEntity.ok("login ok");
}
์ฟ ํค์ ๋ฌ๋ฆฌ ์ธ์ ๋ฐฉ์์์๋ ์๋ฒ๊ฐ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๋ค๋ ์ ์ด ํฌ์ธํธ์ ๋๋ค.
์ธ์ ์ด ์ ์ง๋๋ ๋์์ ์๋ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ณ์ ์ ์ฅํ๊ณ ์์ด์ผ ํฉ๋๋ค.
์ฆ, ์๋ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ์ด๋ ๋ถ๋ถ์ด ๊ณ์ ์ ์ ๋นํ๊ณ ์์ต๋๋ค. ์ด๋ ๊ฒ ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ๊ธฐ์ตํ๋ ๊ฒ์ Stateful(์ํ ์ ์ง)๋ผ๊ณ ํฉ๋๋ค.
์ด ๋๋ฌธ์ Redis(key- value ๊ตฌ์กฐ์ ๊ณ ์ฑ๋ฅ ์ ์ฅ์)์ ์ธ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ธฐ๋ ํฉ๋๋ค.
์ธ์ ๋ฐฉ์์ ์ฅ์
- ์๋ฒ์์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ ์ฟ ํค ๋ฐฉ์๋ณด๋ค ์์ ํฉ๋๋ค.
- ๋ธ๋ผ์ฐ์ ๊ฐ ์ฟ ํค๋ฅผ ์๋์ผ๋ก ๋ถ์ฌ์ฃผ๋ฏ๋ก ์๋ฒ์์๋ CSRF ํ ํฐ ์ ๋ต๋ง ๋ง๋ จํ๋ฉด ๋ฉ๋๋ค.
- CSRF ํ ํฐ์ด๋ ๋ก๊ทธ์ธ ์ ์๋ฒ๊ฐ ๋ฐํํด์ฃผ๋ ํ ํฐ์ผ๋ก, ํด๋ผ์ด์ธํธ์ ๊ณต์ ๋๋ ์ธ์ฆ ๊ฐ์
๋๋ค.
ํด๋ผ์ด์ธํธ๋ ์ฌ๋ฐ๋ฅธ ํ ํฐ ๊ฐ์ ํฌํจํด์ผ ์๋ฒ์ ์์ฒญ์ ํ ์ ์์ต๋๋ค.
- CSRF ํ ํฐ์ด๋ ๋ก๊ทธ์ธ ์ ์๋ฒ๊ฐ ๋ฐํํด์ฃผ๋ ํ ํฐ์ผ๋ก, ํด๋ผ์ด์ธํธ์ ๊ณต์ ๋๋ ์ธ์ฆ ๊ฐ์
๋๋ค.
- ์๋ฒ ์ธก์์ ์ธ์ ์ ์ฝ๊ฒ ๋ฌดํจํํ ์ ์์ต๋๋ค. ์ด๋ ์ฌ์ฉ์์ ์ ๊ทผ์ด ๋น์ ์์ ์ผ๋ก ๋ณด์ด๋ฉด ๋ฐ๋ก ๋ก๊ทธ์์์ํฌ ์ ์๋๊ฑฐ์ฃ .
์ธ์ ๋ฐฉ์์ ๋จ์
- ์๋ฒ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ ์ฅํด์ผ ํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ๋ Redis ๋ฑ ์ธ์ ์ ์ฅ์ ์ด์ ๋น์ฉ ๋ถ๋ด์ด ์์ต๋๋ค.
- ๋ชจ๋ฐ์ผ ์ฑ์ด๋ SPA์์๋ ์ฟ ํค ๋ค๋ฃจ๊ธฐ๊ฐ ๋ฒ๊ฑฐ๋ก์ธ ์ ์์ต๋๋ค.
- SPA๋? Single Page Application์ผ๋ก ๋ชจ๋ ํ์ด์ง๋ฅผ ๊ฐ์ ธ์ค์ง ์๊ณ ,
ํ์ํ ์ปจํ ์ธ ๋ฅผ ์๋ฒ์์ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฐ์ ธ์ ํ์ฌ ํ์ด์ง ๋ด์์ ์ ๋ฐ์ดํธํ๋ ๋ชจ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ค.
- SPA๋? Single Page Application์ผ๋ก ๋ชจ๋ ํ์ด์ง๋ฅผ ๊ฐ์ ธ์ค์ง ์๊ณ ,
๐ช JWT ๋ฐฉ์
JWT ๋ฐฉ์์ ํ ํฐ์ ์ด์ฉํ๋ ๋ฐฉ์์ ๋๋ค.
JWT๋ Json Web Token์ ์ฝ์๋ก, ์์ฃผ ๊ธด ๋ฌธ์์ด๋ก ๋์ด ์์ต๋๋ค.
1. ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์ ๋ก๊ทธ์ธ ์์ฒญ์ ๋ณด๋ ๋๋ค.
2. ์๋ฒ์์๋ ์ธ์ฆ ํ ์๋ต์ ํ ํฐ์ ๋ด์ (ํค๋ ๋๋ ์ฟ ํค๋ก) ๋ณด๋ ๋๋ค.
3. ํด๋ผ์ด์ธํธ๋ ์ด ํ ํฐ์ ์ด๋๊ฐ(๋ก์ปฌ ์คํ ๋ฆฌ์ง ๋ฑ)์ ์ ์ฅํฉ๋๋ค.
4. ํด๋ผ์ด์ธํธ๋ ์ดํ ์ธ๊ฐ ์์ฒญ ์๋ง๋ค ํ ํฐ์ ํจ๊ป ๋ด์ ๋ณด๋ ๋๋ค.
5. ์๋ฒ์์๋ ์ฌ๋ฐ๋ฅธ ํ ํฐ์ธ์ง ํ์ธ ํ ์ธ๊ฐ ์ฒ๋ฆฌ๋ฅผ ํฉ๋๋ค.
์ด์ ๋ฐฉ์๋ค๊ณผ์ ์ฐจ์ด์ ์ ์ฟ ํค๊ฐ ์๋ JWT ํ ํฐ์ ์ฃผ๊ณ ๋ฐ๋๋ค๋ ์ ๊ณผ
ํ ํฐ์๋ ๋ง๋ฃ ์๊ฐ์ด ์๊ณ , ์๋ฒ์์ ์์ง ๋ง๋ฃ์๊ฐ์ด ๋จ์๋์ง, ์ฌ์ฉ์๊ฐ ๋ง๋์ง ๋ฑ ์ ํจํ ํ ํฐ์ธ์ง ๊ฒ์ฆํ๋ ๋จ๊ณ๊ฐ ์๋ค๋ ์ ์ ๋๋ค.
์ด ํ ํฐ์ ์ด ์๋ฒ์์๋ง ์ฌ์ฉํ๋ ์ํฌ๋ฆฟ ํค๋ผ๋ ํน์ดํ ๊ฐ๊ณผ ํน์ ์๊ณ ๋ฆฌ์ฆ๋ค์ ๋ฐ๋ผ ๋ง๋ค์ด์ง๋๋ค.
ํค๋์ ํ์ด๋ก๋, ์๊ทธ๋์ฒ๋ก ๊ตฌ์ฑ์ด ๋๋๋ฐ ์ค๋ ๊ธ์์๋ JWT ํ ํฐ ๋ง๋๋ ๋ฒ์ ๋ํด์๋ ๋์ด๊ฐ๊ฒ ์ต๋๋ค.

์๋ฒ์์๋ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ์ ์ฅํ์ง ์์ต๋๋ค.
์ฒ์ ์ธ์ฆ ์์ฒญ์์๋ง ํ ํฐ์ ๋ฐ๊ธํ๊ณ , ์ดํ ์์ฒญ์์๋ ๋ ํด๋ผ์ด์ธํธ๊ฐ ํ ํฐ์ ๋ด๊ณ ์์ฒญ์ ํ๋
๋งค๋ฒ ํ ํฐ์ ๊ฒ์ฆํฉ๋๋ค. ์ด์ฒ๋ผ ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ์ ์ฅํ์ง ์์ผ๋ฏ๋ก Stateless ํฉ๋๋ค.
JWT ๋ฐฉ์์ ์ฅ์
- ์๋ฒ๋ Statelessํ๊ธฐ ๋๋ฌธ์ ์๋ฒ ์ธก์ ๋ถํ๊ฐ ๋ฎ์ต๋๋ค. ์๋ฒ ์ธ์คํด์ค๊ฐ ์ฌ๋ฌ ๋ ํ์ฅ๋์ด๋, ์ธ์ ๊ณต์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.
- API ๊ฒ์ดํธ์จ์ด๋ ๋ชจ๋ฐ์ผ ๋ค์ดํฐ๋ธ ์ฐ๋์ด ์ธ์ ์ ๋นํด ์์ํฉ๋๋ค.
JWT ๋ฐฉ์์ ๋จ์
- ํ ํฐ์ด ํ์ทจ๋นํ๋ฉด ๋ง๋ฃ๋๊ธฐ ์ ๊น์ง๋ ํด์ปค๋ฅผ ๋ง์ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
- ํ ๋ฒ ๋ฐ๊ธ๋ ํ ํฐ์ ์์์ ๋ง๋ฃ๋๊ธฐ ์ ๊น์ง ์์ ์ด๋ ํ๊ธฐ๊ฐ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
- ์ด๋ฅผ ๋ณด์ํ๊ธฐ ์ํด ๋ง๋ฃ ์๊ฐ์ด ์งง์ AccessToken๊ณผ ๋ง๋ฃ ์๊ฐ์ด ๊ธด Refresh Token์ ๋ ๋ค ๋ฐ๊ธํ๊ณ , AccessToken ๋ง๋ฃ ์ Refresh Token์ ์ด์ฉํด Access Token์ ์๋ก ๋ฐ๊ธ ๋ฐ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ด๋ฌ๋ฉด AccessToken์ด ํ์ทจ๋์ด๋ ๊ธ๋ฐฉ ๋ง๋ฃ๋ ํ ๋ ํด์ปค๊ฐ ์์ง์ผ ์ ์๋ ์๊ฐ์ด ์งง์์ง๋๋ค.