Browse Source

๐ŸŒ Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md` (#13333)

pull/13478/head
Lee Yesong 4 weeks ago
committed by GitHub
parent
commit
3565ea00b6
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 273
      docs/ko/docs/tutorial/security/oauth2-jwt.md

273
docs/ko/docs/tutorial/security/oauth2-jwt.md

@ -0,0 +1,273 @@
# ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ์„ ์ด์šฉํ•œ OAuth2, JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” Bearer ์ธ์ฆ
๋ชจ๋“  ๋ณด์•ˆ ํ๋ฆ„์„ ๊ตฌ์„ฑํ–ˆ์œผ๋ฏ€๋กœ, ์ด์ œ <abbr title="JSON Web Tokens">JWT</abbr> ํ† ํฐ๊ณผ ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ์„ ์‚ฌ์šฉํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ฝ”๋“œ๋Š” ์‹ค์ œ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํŒจ์Šค์›Œ๋“œ๋ฅผ ํ•ด์‹ฑํ•˜์—ฌ DB์— ์ €์žฅํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด์ „ ์žฅ์— ์ด์–ด์„œ ์‹œ์ž‘ํ•ด ๋ด…์‹œ๋‹ค.
## JWT
JWT ๋Š” "JSON Web Tokens" ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
JSON ๊ฐ์ฒด๋ฅผ ๊ณต๋ฐฑ์ด ์—†๋Š” ๊ธด ๋ฌธ์ž์—ด๋กœ ์ธ์ฝ”๋”ฉํ•˜๋Š” ํ‘œ์ค€์ด๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค:
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```
JWT๋Š” ์•”ํ˜ธํ™”๋˜์ง€ ์•Š์•„ ๋ˆ„๊ตฌ๋“ ์ง€ ํ† ํฐ์—์„œ ์ •๋ณด๋ฅผ ๋ณต์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ JWT๋Š” ์„œ๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ž์‹ ์ด ๋ฐœ๊ธ‰ํ•œ ํ† ํฐ์„ ๋ฐ›์•˜์„ ๋•Œ, ์‹ค์ œ๋กœ ์ž์‹ ์ด ๋ฐœ๊ธ‰ํ•œ๊ฒŒ ๋งž๋Š”์ง€ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด ์ผ์ฃผ์ผ์ธ ํ† ํฐ์„ ๋ฐœํ–‰ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. ๋‹ค์Œ ๋‚  ์‚ฌ์šฉ์ž๊ฐ€ ํ† ํฐ์„ ๊ฐ€์ ธ์™”์„ ๋•Œ, ๊ทธ ์‚ฌ์šฉ์ž๊ฐ€ ์‹œ์Šคํ…œ์— ์—ฌ์ „ํžˆ ๋กœ๊ทธ์ธ๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ผ์ฃผ์ผ ๋’ค์—๋Š” ํ† ํฐ์ด ๋งŒ๋ฃŒ๋  ๊ฒƒ์ด๊ณ , ์‚ฌ์šฉ์ž๋Š” ์ธ๊ฐ€๋˜์ง€ ์•Š์•„ ์ƒˆ ํ† ํฐ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์‚ฌ์šฉ์ž(๋˜๋Š” ์ œ3์ž)๊ฐ€ ํ† ํฐ์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ๋งŒ๋ฃŒ์ผ์„ ๋ณ€๊ฒฝํ•˜๋ฉด, ์„œ๋ช…์ด ์ผ์น˜ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์•Œ์•„์ฑŒ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋งŒ์•ฝ JWT ํ† ํฐ์„ ๋‹ค๋ค„๋ณด๊ณ , ์ž‘๋™ ๋ฐฉ์‹๋„ ์•Œ์•„๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a> ์„ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.
## `PyJWT` ์„ค์น˜
ํŒŒ์ด์ฌ์œผ๋กœ JWT ํ† ํฐ์„ ์ƒ์„ฑํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋ ค๋ฉด `PyJWT` ๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
[๊ฐ€์ƒํ™˜๊ฒฝ](../../virtual-environments.md){.internal-link target=_blank} ์„ ๋งŒ๋“ค๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ `pyjwt` ๋ฅผ ์„ค์น˜ํ•˜์‹ญ์‹œ์˜ค:
<div class="termy">
```console
$ pip install pyjwt
---> 100%
```
</div>
/// info | ์ฐธ๊ณ 
RSA๋‚˜ ECDSA ๊ฐ™์€ ์ „์ž ์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, `pyjwt[crypto]`๋ผ๋Š” ์•”ํ˜ธํ™” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ <a href="https://pyjwt.readthedocs.io/en/latest/installation.html" class="external-link" target="_blank">PyJWT ์„ค์น˜</a> ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
///
## ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ
"ํ•ด์‹ฑ(Hashing)"์€ ์–ด๋–ค ๋‚ด์šฉ(์—ฌ๊ธฐ์„œ๋Š” ํŒจ์Šค์›Œ๋“œ)์„ ํ•ด์„ํ•  ์ˆ˜ ์—†๋Š” ์ผ๋ จ์˜ ๋ฐ”์ดํŠธ ์ง‘ํ•ฉ(๋‹จ์ˆœ ๋ฌธ์ž์—ด)์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
๋™์ผํ•œ ๋‚ด์šฉ(๋˜‘๊ฐ™์€ ํŒจ์Šค์›Œ๋“œ)์„ ํ•ด์‹ฑํ•˜๋ฉด ๋™์ผํ•œ ๋ฌธ์ž์—ด์„ ์–ป์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๊ทธ ๋ฌธ์ž์—ด์„ ๋‹ค์‹œ ํŒจ์Šค์›Œ๋“œ๋กœ ๋˜๋Œ๋ฆด ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.
### ํŒจ์Šค์›Œ๋“œ๋ฅผ ํ•ด์‹ฑํ•˜๋Š” ์ด์œ 
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํƒˆ์ทจ๋‹นํ•˜๋”๋ผ๋„, ์นจ์ž…์ž๋Š” ์‚ฌ์šฉ์ž์˜ ํ‰๋ฌธ ํŒจ์Šค์›Œ๋“œ ๋Œ€์‹  ํ•ด์‹œ ๊ฐ’๋งŒ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ์นจ์ž…์ž๋Š” ํ›”์นœ ์‚ฌ์šฉ์ž ํŒจ์Šค์›Œ๋“œ๋ฅผ ๋‹ค๋ฅธ ์‹œ์Šคํ…œ์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (๋Œ€๋‹ค์ˆ˜ ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ ์‹œ์Šคํ…œ์—์„œ ๋™์ผํ•œ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ‰๋ฌธ ํŒจ์Šค์›Œ๋“œ๊ฐ€ ์œ ์ถœ๋˜๋ฉด ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค.)
## `passlib` ์„ค์น˜
PassLib๋Š” ํŒจ์Šค์›Œ๋“œ ํ•ด์‹œ๋ฅผ ๋‹ค๋ฃจ๋Š” ํ›Œ๋ฅญํ•œ ํŒŒ์ด์ฌ ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค.
๋งŽ์€ ์•ˆ์ „ํ•œ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๋„๊ตฌ๋“ค์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
์ถ”์ฒœํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ "Bcrypt"์ž…๋‹ˆ๋‹ค.
[๊ฐ€์ƒํ™˜๊ฒฝ](../../virtual-environments.md){.internal-link target=_blank} ์„ ๋งŒ๋“ค๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ PassLib์™€ Bcrypt๋ฅผ ์„ค์น˜ํ•˜์‹ญ์‹œ์˜ค:
<div class="termy">
```console
$ pip install "passlib[bcrypt]"
---> 100%
```
</div>
/// tip | ํŒ
`passlib`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, **Django**, **Flask** ์˜ ๋ณด์•ˆ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด๋‚˜ ๋‹ค๋ฅธ ๋„๊ตฌ๋กœ ์ƒ์„ฑํ•œ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์ž๋ฉด, FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ Django ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Django ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ ์ง„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๋Š” FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ Django ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋™์‹œ์— ๋กœ๊ทธ์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
///
## ํŒจ์Šค์›Œ๋“œ์˜ ํ•ด์‹œ์™€ ๊ฒ€์ฆ
ํ•„์š”ํ•œ ๋„๊ตฌ๋ฅผ `passlib`์—์„œ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค.
PassLib "์ปจํ…์ŠคํŠธ(context)"๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํŒจ์Šค์›Œ๋“œ๋ฅผ ํ•ด์‹ฑํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
/// tip | ํŒ
PassLib ์ปจํ…์ŠคํŠธ๋Š” ๋‹ค์–‘ํ•œ ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, ๋” ์ด์ƒ ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š” ์˜ค๋ž˜๋œ ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ฒ€์ฆํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค๋ฅธ ์‹œ์Šคํ…œ(Django ๊ฐ™์€)์—์„œ ์ƒ์„ฑํ•œ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ฝ๊ณ  ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ƒˆ๋กœ์šด ํŒจ์Šค์›Œ๋“œ๋ฅผ Bcrypt ๊ฐ™์€ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ํ•ด์‹ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋™์‹œ์— ๊ทธ๋Ÿฐ ๋ชจ๋“  ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
///
์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ํŒจ์Šค์›Œ๋“œ๋ฅผ ํ•ด์‹ฑํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋ฐ›์€ ํŒจ์Šค์›Œ๋“œ๊ฐ€ ์ €์žฅ๋œ ํ•ด์‹œ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}
/// note
์ƒˆ๋กœ์šด (๊ฐ€์งœ) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค `fake_users_db`๋ฅผ ํ™•์ธํ•˜๋ฉด, ํ•ด์‹œ ์ฒ˜๋ฆฌ๋œ ํŒจ์Šค์›Œ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
///
## JWT ํ† ํฐ ์ฒ˜๋ฆฌ
์„ค์น˜๋œ ๋ชจ๋“ˆ์„ ์ž„ํฌํŠธ ํ•ฉ๋‹ˆ๋‹ค.
JWT ํ† ํฐ ์„œ๋ช…์— ์‚ฌ์šฉ๋  ์ž„์˜์˜ ๋น„๋ฐ€ํ‚ค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
์•ˆ์ „ํ•œ ์ž„์˜์˜ ๋น„๋ฐ€ํ‚ค๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค:
<div class="termy">
```console
$ openssl rand -hex 32
09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
```
</div>
๊ทธ๋ฆฌ๊ณ  ์ƒ์„ฑํ•œ ๋น„๋ฐ€ํ‚ค๋ฅผ ๋ณต์‚ฌํ•ด ๋ณ€์ˆ˜ `SECRET_KEY`์— ๋Œ€์ž…ํ•ฉ๋‹ˆ๋‹ค. (์ด ์˜ˆ์ œ์˜ ๋ณ€์ˆ˜ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.)
JWT ํ† ํฐ์„ ์„œ๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์œ„ํ•œ ๋ณ€์ˆ˜ `ALGORITHM` ์„ ์ƒ์„ฑํ•˜๊ณ  `"HS256"` ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
ํ† ํฐ ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์„ ์œ„ํ•œ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
์‘๋‹ต์„ ์œ„ํ•œ ํ† ํฐ ์—”๋“œํฌ์ธํŠธ์— ์‚ฌ์šฉ๋  Pydantic ๋ชจ๋ธ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
์ƒˆ ์•ก์„ธ์Šค ํ† ํฐ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
## ์˜์กด์„ฑ ์ˆ˜์ •
`get_current_user` ํ•จ์ˆ˜๋ฅผ ์ด์ „๊ณผ ๋™์ผํ•œ ํ† ํฐ์„ ๋ฐ›๋„๋ก ์ˆ˜์ •ํ•˜๋˜, ์ด๋ฒˆ์—๋Š” JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
๋ฐ›์€ ํ† ํฐ์„ ๋””์ฝ”๋”ฉํ•˜์—ฌ ๊ฒ€์ฆํ•œ ํ›„ ํ˜„์žฌ ์‚ฌ์šฉ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
ํ† ํฐ์ด ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๋ฉด HTTP ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
## `/token` ๊ฒฝ๋กœ ์ž‘์—… ์ˆ˜์ •
ํ† ํฐ์˜ ๋งŒ๋ฃŒ ์‹œ๊ฐ์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด `timedelta` ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
์‹ค์ œ JWT ์•ก์„ธ์Šค ํ† ํฐ์„ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
### JWT "์ฃผ์ฒด(subject)" `sub`์— ๋Œ€ํ•œ ๊ธฐ์ˆ  ์„ธ๋ถ€ ์‚ฌํ•ญ
JWT ๋ช…์„ธ์— ๋”ฐ๋ฅด๋ฉด ํ† ํฐ์˜ ์ฃผ์ฒด๋ฅผ ํฌํ•จํ•˜๋Š” `sub`๋ผ๋Š” ํ‚ค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์‚ฌ์šฉ ์—ฌ๋ถ€๋Š” ์„ ํƒ์‚ฌํ•ญ์ด์ง€๋งŒ, ์‚ฌ์šฉ์ž์˜ ์‹๋ณ„ ์ •๋ณด๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ๋Š” ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
JWT๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ API๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ ๋‹ค๋ฅธ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด "์ž๋™์ฐจ"๋‚˜ "๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ"์„ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  "์ž๋™์ฐจ๋ฅผ ์šด์ „ํ•˜๋‹ค"๋‚˜ "๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์„ ์ˆ˜์ •ํ•˜๋‹ค"์ฒ˜๋Ÿผ ํ•ด๋‹น ์—”ํ„ฐํ‹ฐ์— ๋Œ€ํ•œ ๊ถŒํ•œ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ ํ›„ ์ด JWT ํ† ํฐ์„ ์‚ฌ์šฉ์ž(๋˜๋Š” ๋ด‡)์—๊ฒŒ ์ œ๊ณตํ•˜๋ฉด, ๊ทธ๋“ค์€ ๊ณ„์ •์„ ๋”ฐ๋กœ ๋งŒ๋“ค ํ•„์š” ์—†์ด API๊ฐ€ ์ƒ์„ฑํ•œ JWT ํ† ํฐ๋งŒ์œผ๋กœ ์ž‘์—…(์ž๋™์ฐจ ์šด์ „ ๋˜๋Š” ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ ํŽธ์ง‘)์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋Ÿฌํ•œ ๊ฐœ๋…์„ ํ™œ์šฉํ•˜๋ฉด JWT๋Š” ํ›จ์”ฌ ๋” ๋ณต์žกํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ ์—ฌ๋Ÿฌ ์—”ํ„ฐํ‹ฐ๊ฐ€ ๋™์ผํ•œ ID๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด foo๋ผ๋Š” ID๋ฅผ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž, ์ž๋™์ฐจ, ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ ID ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด, ์‚ฌ์šฉ์ž์˜ JWT ํ† ํฐ์„ ์ƒ์„ฑํ•  ๋•Œ ์ ‘๋‘์‚ฌ๋กœ `sub` ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `username:` ์„ ๋ถ™์ด๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด ์˜ˆ์ œ์—์„œ๋Š” `sub` ๊ฐ’์ด `username:johndoe`์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ ์€ `sub` ํ‚ค๋Š” ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ณ ์œ ํ•œ ์‹๋ณ„์ž๊ฐ€ ๋˜์–ด์•ผ ํ•˜๋ฉฐ ๋ฌธ์ž์—ด์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.
## ํ™•์ธํ•ด๋ด…์‹œ๋‹ค
์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋ฌธ์„œ๋กœ ์ด๋™ํ•˜์‹ญ์‹œ์˜ค: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
<img src="/img/tutorial/security/image07.png">
์ด์ „๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ธ์ฆํ•˜์‹ญ์‹œ์˜ค.
๋‹ค์Œ ์ธ์ฆ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค:
Username: `johndoe`
Password: `secret`
/// check
์ฝ”๋“œ ์–ด๋””์—๋„ ํ‰๋ฌธ ํŒจ์Šค์›Œ๋“œ "`secret`" ์ด ์—†๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์‹ญ์‹œ์˜ค. ํ•ด์‹œ๋œ ๋ฒ„์ „๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.
///
<img src="/img/tutorial/security/image08.png">
`/users/me/` ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‘๋‹ต์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
```JSON
{
"username": "johndoe",
"email": "[email protected]",
"full_name": "John Doe",
"disabled": false
}
```
<img src="/img/tutorial/security/image09.png">
๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋ฅผ ์—ด์–ด๋ณด๋ฉด ์ „์†ก๋œ ๋ฐ์ดํ„ฐ์— ํ† ํฐ๋งŒ ํฌํ•จ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŒจ์Šค์›Œ๋“œ๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•˜๊ณ  ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐ›๊ธฐ ์œ„ํ•œ ์ฒซ ๋ฒˆ์งธ ์š”์ฒญ์—๋งŒ ์ „์†ก๋˜๋ฉฐ, ์ดํ›„์—๋Š” ์ „์†ก๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:
<img src="/img/tutorial/security/image10.png">
/// note
`Bearer `๋กœ ์‹œ์ž‘ํ•˜๋Š” `Authorization` ํ—ค๋”์— ์ฃผ๋ชฉํ•˜์‹ญ์‹œ์˜ค.
///
## `scopes` ์˜ ๊ณ ๊ธ‰ ์‚ฌ์šฉ๋ฒ•
OAuth2๋Š” "์Šค์ฝ”ํ”„(scopes)" ๋ผ๋Š” ๊ฐœ๋…์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JWT ํ† ํฐ์— ํŠน์ • ๊ถŒํ•œ ์ง‘ํ•ฉ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ ํ›„ ์ด ํ† ํฐ์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ง์ ‘ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜ ์ œ3์ž์—๊ฒŒ ์ œ๊ณตํ•˜์—ฌ, ํŠน์ • ์ œํ•œ์‚ฌํ•ญ ํ•˜์—์žˆ๋Š” API์™€ ํ†ต์‹ ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**FastAPI** ์—์„œ์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•๊ณผ ํ†ตํ•ฉ ๋ฐฉ์‹์€ **์‹ฌํ™” ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ** ์—์„œ ์ž์„ธํžˆ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
## ์š”์•ฝ
์ง€๊ธˆ๊นŒ์ง€ ์‚ดํŽด๋ณธ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ, OAuth2์™€ JWT ๊ฐ™์€ ํ‘œ์ค€์„ ์‚ฌ์šฉํ•˜์—ฌ ์•ˆ์ „ํ•œ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฑฐ์˜ ๋ชจ๋“  ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋ณด์•ˆ ์ฒ˜๋ฆฌ๋Š” ์ƒ๋‹นํžˆ ๋ณต์žกํ•œ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค.
์ด๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๋Š” ๋งŽ์€ ํŒจํ‚ค์ง€๋Š” ๋ฐ์ดํ„ฐ ๋ชจ๋ธ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ธฐ๋Šฅ๋“ค์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ์ œ์•ฝ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ง€๋‚˜์น˜๊ฒŒ ๋‹จ์ˆœํ™”ํ•˜๋Š” ์ผ๋ถ€ ํŒจํ‚ค์ง€๋“ค์€ ์‹ฌ๊ฐํ•œ ๋ณด์•ˆ ๊ฒฐํ•จ์„ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
---
**FastAPI** ๋Š” ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ๋ฐ์ดํ„ฐ ๋ชจ๋ธ, ๋„๊ตฌ๋„ ๊ฐ•์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
ํ”„๋กœ์ ํŠธ์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๊ฒƒ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  `passlib` ์™€ `PyJWT` ์ฒ˜๋Ÿผ ์ž˜ ๊ด€๋ฆฌ๋˜๊ณ  ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํŒจํ‚ค์ง€๋“ค์„ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. **FastAPI** ๋Š” ์™ธ๋ถ€ ํŒจํ‚ค์ง€ ํ†ตํ•ฉ์„ ์œ„ํ•ด ๋ณต์žกํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ํ•„์š”ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์œ ์—ฐ์„ฑ, ๊ฒฌ๊ณ ์„ฑ, ๋ณด์•ˆ์„ฑ์„ ํ•ด์น˜์ง€ ์•Š์œผ๋ฉด์„œ ๊ณผ์ •์„ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  OAuth2์™€ ๊ฐ™์€ ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ์„ ๋น„๊ต์  ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋” ์„ธ๋ถ„ํ™”๋œ ๊ถŒํ•œ ์ฒด๊ณ„๋ฅผ ์œ„ํ•ด OAuth2์˜ "์Šค์ฝ”ํ”„"๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ **์‹ฌํ™” ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ**์—์„œ ๋” ์ž์„ธํžˆ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. OAuth2์˜ ์Šค์ฝ”ํ”„๋Š” ์ œ3์ž ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉ์ž๋ฅผ ๋Œ€์‹ ํ•ด ๊ทธ๋“ค์˜ API์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋„๋ก ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๊ธฐ ์œ„ํ•ด, Facebook, Google, GitHub, Microsoft, Twitter ๋“ฑ์˜ ๋งŽ์€ ๋Œ€ํ˜• ์ธ์ฆ ์ œ๊ณต์—…์ฒด๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค.
Loadingโ€ฆ
Cancel
Save