Browse Source

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

pull/4492/merge
DoHyun Kim 1 year ago
committed by GitHub
parent
commit
d6997ab2a0
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 315
      docs/ko/docs/tutorial/security/simple-oauth2.md

315
docs/ko/docs/tutorial/security/simple-oauth2.md

@ -0,0 +1,315 @@
# ํŒจ์Šค์›Œ๋“œ์™€ Bearer๋ฅผ ์ด์šฉํ•œ ๊ฐ„๋‹จํ•œ OAuth2
์ด์ œ ์ด์ „ ์žฅ์—์„œ ๋นŒ๋“œํ•˜๊ณ  ๋ˆ„๋ฝ๋œ ๋ถ€๋ถ„์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์™„์ „ํ•œ ๋ณด์•ˆ ํ๋ฆ„์„ ๊ฐ–๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
## `username`์™€ `password` ์–ป๊ธฐ
**FastAPI** ๋ณด์•ˆ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ `username` ๋ฐ `password`๋ฅผ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
OAuth2๋Š” (์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”) "ํŒจ์Šค์›Œ๋“œ ํ”Œ๋กœ์šฐ"์„ ์‚ฌ์šฉํ•  ๋•Œ ํด๋ผ์ด์–ธํŠธ/์œ ์ €๊ฐ€ `username` ๋ฐ `password` ํ•„๋“œ๋ฅผ ํผ ๋ฐ์ดํ„ฐ๋กœ ๋ณด๋‚ด์•ผ ํ•จ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์‚ฌ์–‘์—๋Š” ํ•„๋“œ์˜ ์ด๋ฆ„์„ ๊ทธ๋ ‡๊ฒŒ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ `user-name` ๋˜๋Š” `email`์€ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๊ฑฑ์ •ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. ํ”„๋ŸฐํŠธ์—”๋“œ์—์„œ ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ์›ํ•˜๋Š” ๋Œ€๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ์€ ์›ํ•˜๋Š” ๋‹ค๋ฅธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ๋กœ๊ทธ์ธ *๊ฒฝ๋กœ ์ž‘๋™*์˜ ๊ฒฝ์šฐ ์‚ฌ์–‘๊ณผ ํ˜ธํ™˜๋˜๋„๋ก ์ด๋Ÿฌํ•œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด ํ†ตํ•ฉ API ๋ฌธ์„œ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค).
์‚ฌ์–‘์—๋Š” ๋˜ํ•œ `username`๊ณผ `password`๊ฐ€ ํผ ๋ฐ์ดํ„ฐ๋กœ ์ „์†ก๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ๋ช…์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค(๋”ฐ๋ผ์„œ ์—ฌ๊ธฐ์—๋Š” JSON์ด ์—†์Šต๋‹ˆ๋‹ค).
### `scope`
์‚ฌ์–‘์—๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ค๋ฅธ ํผ ํ•„๋“œ "`scope`"๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค.
ํผ ํ•„๋“œ ์ด๋ฆ„์€ `scope`(๋‹จ์ˆ˜ํ˜•)์ด์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ "๋ฒ”์œ„"๊ฐ€ ์žˆ๋Š” ๊ธด ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค.
๊ฐ "๋ฒ”์œ„"๋Š” ๊ณต๋ฐฑ์ด ์—†๋Š” ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค.
์ผ๋ฐ˜์ ์œผ๋กœ ํŠน์ • ๋ณด์•ˆ ๊ถŒํ•œ์„ ์„ ์–ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ๋ด…์‹œ๋‹ค:
* `users:read` ๋˜๋Š” `users:write`๋Š” ์ผ๋ฐ˜์ ์ธ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.
* `instagram_basic`์€ ํŽ˜์ด์Šค๋ถ/์ธ์Šคํƒ€๊ทธ๋žจ์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
* `https://www.googleapis.com/auth/drive`๋Š” Google์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
!!! ์ •๋ณด
OAuth2์—์„œ "๋ฒ”์œ„"๋Š” ํ•„์š”ํ•œ ํŠน์ • ๊ถŒํ•œ์„ ์„ ์–ธํ•˜๋Š” ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค.
`:`๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ๋ฌธ์ž๊ฐ€ ์žˆ๋Š”์ง€ ๋˜๋Š” URL์ธ์ง€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ด๋Ÿฌํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ๊ตฌํ˜„์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
OAuth2์˜ ๊ฒฝ์šฐ ๋ฌธ์ž์—ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.
## `username`๊ณผ `password`๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ฝ”๋“œ
์ด์ œ **FastAPI**์—์„œ ์ œ๊ณตํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
### `OAuth2PasswordRequestForm`
๋จผ์ € `OAuth2PasswordRequestForm`์„ ๊ฐ€์ ธ์™€ `/token`์— ๋Œ€ํ•œ *๊ฒฝ๋กœ ์ž‘๋™*์—์„œ `Depends`์˜ ์˜์กด์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
=== "ํŒŒ์ด์ฌ 3.7 ์ด์ƒ"
```Python hl_lines="4 76"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "ํŒŒ์ด์ฌ 3.10 ์ด์ƒ"
```Python hl_lines="2 74"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
`OAuth2PasswordRequestForm`์€ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ํผ ๋ณธ๋ฌธ์„ ์„ ์–ธํ•˜๋Š” ํด๋ž˜์Šค ์˜์กด์„ฑ์ž…๋‹ˆ๋‹ค:
* `username`.
* `password`.
* `scope`๋Š” ์„ ํƒ์ ์ธ ํ•„๋“œ๋กœ ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋ฌธ์ž์—ด๋กœ ๊ตฌ์„ฑ๋œ ํฐ ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค.
* `grant_type`(์„ ํƒ์ ์œผ๋กœ ์‚ฌ์šฉ).
!!! ํŒ
OAuth2 ์‚ฌ์–‘์€ ์‹ค์ œ๋กœ `password`๋ผ๋Š” ๊ณ ์ • ๊ฐ’์ด ์žˆ๋Š” `grant_type` ํ•„๋“œ๋ฅผ *์š”๊ตฌ*ํ•˜์ง€๋งŒ `OAuth2PasswordRequestForm`์€ ์ด๋ฅผ ๊ฐ•์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด `OAuth2PasswordRequestForm` ๋Œ€์‹  `OAuth2PasswordRequestFormStrict`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
* `client_id`(์„ ํƒ์ ์œผ๋กœ ์‚ฌ์šฉ) (์˜ˆ์ œ์—์„œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค).
* `client_secret`(์„ ํƒ์ ์œผ๋กœ ์‚ฌ์šฉ) (์˜ˆ์ œ์—์„œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค).
!!! ์ •๋ณด
`OAuth2PasswordRequestForm`์€ `OAuth2PasswordBearer`์™€ ๊ฐ™์ด **FastAPI**์— ๋Œ€ํ•œ ํŠน์ˆ˜ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.
`OAuth2PasswordBearer`๋Š” **FastAPI**๊ฐ€ ๋ณด์•ˆ ์ฒด๊ณ„์ž„์„ ์•Œ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ OpenAPI์— ๊ทธ๋ ‡๊ฒŒ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ `OAuth2PasswordRequestForm`์€ ์ง์ ‘ ์ž‘์„ฑํ•˜๊ฑฐ๋‚˜ `Form` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง์ ‘ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค ์˜์กด์„ฑ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€์ด๋ฏ€๋กœ ๋” ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด **FastAPI**์—์„œ ์ง์ ‘ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
### ํผ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉํ•˜๊ธฐ
!!! ํŒ
์ข…์†์„ฑ ํด๋ž˜์Šค `OAuth2PasswordRequestForm`์˜ ์ธ์Šคํ„ด์Šค์—๋Š” ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๊ธด ๋ฌธ์ž์—ด์ด ์žˆ๋Š” `scope` ์†์„ฑ์ด ์—†๊ณ  ๋Œ€์‹  ์ „์†ก๋œ ๊ฐ ๋ฒ”์œ„์— ๋Œ€ํ•œ ์‹ค์ œ ๋ฌธ์ž์—ด ๋ชฉ๋ก์ด ์žˆ๋Š” `scopes` ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์˜ˆ์ œ์—์„œ๋Š” `scopes`๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
์ด์ œ ํผ ํ•„๋“œ์˜ `username`์„ ์‚ฌ์šฉํ•˜์—ฌ (๊ฐ€์งœ) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์œ ์ € ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
ํ•ด๋‹น ์‚ฌ์šฉ์ž๊ฐ€ ์—†์œผ๋ฉด "์ž˜๋ชป๋œ ์‚ฌ์šฉ์ž ์ด๋ฆ„ ๋˜๋Š” ํŒจ์Šค์›Œ๋“œ"๋ผ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.
์˜ค๋ฅ˜์˜ ๊ฒฝ์šฐ `HTTPException` ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
=== "ํŒŒ์ด์ฌ 3.7 ์ด์ƒ"
```Python hl_lines="3 77-79"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "ํŒŒ์ด์ฌ 3.10 ์ด์ƒ"
```Python hl_lines="1 75-77"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
### ํŒจ์Šค์›Œ๋“œ ํ™•์ธํ•˜๊ธฐ
์ด ์‹œ์ ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ ํ˜•์‹์„ ํ™•์ธํ–ˆ์ง€๋งŒ ์•”ํ˜ธ๋ฅผ ํ™•์ธํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
๋จผ์ € ๋ฐ์ดํ„ฐ๋ฅผ Pydantic `UserInDB` ๋ชจ๋ธ์— ๋„ฃ๊ฒ ์Šต๋‹ˆ๋‹ค.
์ผ๋ฐ˜ ํ…์ŠคํŠธ ์•”ํ˜ธ๋ฅผ ์ €์žฅํ•˜๋ฉด ์•ˆ ๋˜๋‹ˆ (๊ฐ€์งœ) ์•”ํ˜ธ ํ•ด์‹ฑ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๋‘ ํŒจ์Šค์›Œ๋“œ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ๋™์ผํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.
#### ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ
"ํ•ด์‹ฑ"์€ ์ผ๋ถ€ ์ฝ˜ํ…์ธ (์ด ๊ฒฝ์šฐ ํŒจ์Šค์›Œ๋“œ)๋ฅผ ํšก์„ค์ˆ˜์„คํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ์ผ๋ จ์˜ ๋ฐ”์ดํŠธ(๋ฌธ์ž์—ด)๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
์ •ํ™•ํžˆ ๋™์ผํ•œ ์ฝ˜ํ…์ธ (์ •ํ™•ํžˆ ๋™์ผํ•œ ํŒจ์Šค์›Œ๋“œ)๋ฅผ ์ „๋‹ฌํ•  ๋•Œ๋งˆ๋‹ค ์ •ํ™•ํžˆ ๋™์ผํ•œ ํšก์„ค์ˆ˜์„ค์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ํšก์„ค์ˆ˜์„ค์—์„œ ์•”ํ˜ธ๋กœ ๋‹ค์‹œ ๋ณ€ํ™˜ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.
##### ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ 
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์œ ์ถœ๋œ ๊ฒฝ์šฐ ํ•ด์ปค๋Š” ์‚ฌ์šฉ์ž์˜ ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์•”ํ˜ธ๊ฐ€ ์•„๋‹ˆ๋ผ ํ•ด์‹œ๋งŒ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ํ•ด์ปค๋Š” ๋‹ค๋ฅธ ์‹œ์Šคํ…œ์—์„œ ๋™์ผํ•œ ์•”ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ์‹œ๋„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(๋งŽ์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ๋“  ๊ณณ์—์„œ ๋™์ผํ•œ ์•”ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ด๋Š” ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).
=== "PํŒŒ์ด์ฌ 3.7 ์ด์ƒ"
```Python hl_lines="80-83"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "ํŒŒ์ด์ฌ 3.10 ์ด์ƒ"
```Python hl_lines="78-81"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
#### `**user_dict`์— ๋Œ€ํ•ด
`UserInDB(**user_dict)`๋Š” ๋‹ค์Œ์„ ์˜๋ฏธํ•œ๋‹ค:
*`user_dict`์˜ ํ‚ค์™€ ๊ฐ’์„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ‚ค-๊ฐ’ ์ธ์ˆ˜๋กœ ์ง์ ‘ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค:*
```Python
UserInDB(
username = user_dict["username"],
email = user_dict["email"],
full_name = user_dict["full_name"],
disabled = user_dict["disabled"],
hashed_password = user_dict["hashed_password"],
)
```
!!! ์ •๋ณด
`**user_dict`์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ [**์ถ”๊ฐ€ ๋ชจ๋ธ** ๋ฌธ์„œ](../extra-models.md#about-user_indict){.internal-link target=_blank}๋ฅผ ๋‹ค์‹œ ์ฝ์–ด๋ด…์‹œ๋‹ค.
## ํ† ํฐ ๋ฐ˜ํ™˜ํ•˜๊ธฐ
`token` ์—”๋“œํฌ์ธํŠธ์˜ ์‘๋‹ต์€ JSON ๊ฐ์ฒด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
`token_type`์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” "Bearer" ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ† ํฐ ์œ ํ˜•์€ "`bearer`"์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์•ก์„ธ์Šค ํ† ํฐ์„ ํฌํ•จํ•˜๋Š” ๋ฌธ์ž์—ด๊ณผ ํ•จ๊ป˜ `access_token`์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์—์„œ๋Š” ์™„์ „ํžˆ ์•ˆ์ „ํ•˜์ง€ ์•Š๊ณ , ๋™์ผํ•œ `username`์„ ํ† ํฐ์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
!!! ํŒ
๋‹ค์Œ ์žฅ์—์„œ๋Š” ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ ๋ฐ <abbr title="JSON Web Tokens">JWT</abbr> ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ ๋ณด์•ˆ ๊ตฌํ˜„์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์ง€๊ธˆ์€ ํ•„์š”ํ•œ ์„ธ๋ถ€ ์ •๋ณด์— ์ง‘์ค‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
=== "ํŒŒ์ด์ฌ 3.7 ์ด์ƒ"
```Python hl_lines="85"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "ํŒŒ์ด์ฌ 3.10 ์ด์ƒ"
```Python hl_lines="83"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
!!! ํŒ
์‚ฌ์–‘์— ๋”ฐ๋ผ ์ด ์˜ˆ์ œ์™€ ๋™์ผํ•˜๊ฒŒ `access_token` ๋ฐ `token_type`์ด ํฌํ•จ๋œ JSON์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด๋Š” ์ฝ”๋“œ์—์„œ ์ง์ ‘ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ ํ•ด๋‹น JSON ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์‚ฌ์–‘์„ ์ค€์ˆ˜ํ•˜๊ธฐ ์œ„ํ•ด ์Šค์Šค๋กœ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๊ฑฐ์˜ ์œ ์ผํ•˜๊ฒŒ ๊ธฐ์–ตํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋‚˜๋จธ์ง€๋Š” **FastAPI**๊ฐ€ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
## ์˜์กด์„ฑ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ
์ด์ œ ์˜์กด์„ฑ์„ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•  ๊ฒ๋‹ˆ๋‹ค.
์ด ์‚ฌ์šฉ์ž๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š” *๊ฒฝ์šฐ์—๋งŒ* `current_user`๋ฅผ ๊ฐ€์ ธ์˜ฌ ๊ฒ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ `get_current_user`๋ฅผ ์˜์กด์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ถ”๊ฐ€ ์ข…์†์„ฑ `get_current_active_user`๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
์ด๋Ÿฌํ•œ ์˜์กด์„ฑ ๋ชจ๋‘, ์‚ฌ์šฉ์ž๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ๋น„ํ™œ์„ฑ์ธ ๊ฒฝ์šฐ HTTP ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ์—”๋“œํฌ์ธํŠธ์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์กด์žฌํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ธ์ฆ๋˜์—ˆ์œผ๋ฉฐ ํ™œ์„ฑ ์ƒํƒœ์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉ์ž๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค:
=== "ํŒŒ์ด์ฌ 3.7 ์ด์ƒ"
```Python hl_lines="58-66 69-72 90"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "ํŒŒ์ด์ฌ 3.10 ์ด์ƒ"
```Python hl_lines="55-64 67-70 88"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
!!! ์ •๋ณด
์—ฌ๊ธฐ์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์ด `Bearer`์ธ ์ถ”๊ฐ€ ํ—ค๋” `WWW-Authenticate`๋„ ์‚ฌ์–‘์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค.
๋ชจ๋“  HTTP(์˜ค๋ฅ˜) ์ƒํƒœ ์ฝ”๋“œ 401 "UNAUTHORIZED"๋Š” `WWW-Authenticate` ํ—ค๋”๋„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋ฒ ์–ด๋Ÿฌ ํ† ํฐ์˜ ๊ฒฝ์šฐ(์ง€๊ธˆ์˜ ๊ฒฝ์šฐ) ํ•ด๋‹น ํ—ค๋”์˜ ๊ฐ’์€ `Bearer`์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์‹ค์ œ๋กœ ์ถ”๊ฐ€ ํ—ค๋”๋ฅผ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์—ฌ์ „ํžˆ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์—์„œ๋Š” ์‚ฌ์–‘์„ ์ค€์ˆ˜ํ•˜๋„๋ก ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ ์ด๋ฅผ ์˜ˆ์ƒํ•˜๊ณ  (ํ˜„์žฌ ๋˜๋Š” ๋ฏธ๋ž˜์—) ์‚ฌ์šฉํ•˜๋Š” ๋„๊ตฌ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ˜„์žฌ ๋˜๋Š” ๋ฏธ๋ž˜์— ์ž์‹  ํ˜น์€ ์ž์‹ ์˜ ์œ ์ €๋“ค์—๊ฒŒ ์œ ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ทธ๊ฒƒ์ด ํ‘œ์ค€์˜ ์ด์ ์ž…๋‹ˆ๋‹ค ...
## ํ™•์ธํ•˜๊ธฐ
๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์—ด๊ธฐ: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
### ์ธ์ฆํ•˜๊ธฐ
"Authorize" ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋ด…์‹œ๋‹ค.
์ž๊ฒฉ ์ฆ๋ช…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์œ ์ €๋ช…: `johndoe`
ํŒจ์Šค์›Œ๋“œ: `secret`
<img src="/img/tutorial/security/image04.png">
์‹œ์Šคํ…œ์—์„œ ์ธ์ฆํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค:
<img src="/img/tutorial/security/image05.png">
### ์ž์‹ ์˜ ์œ ์ € ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ
์ด์ œ `/users/me` ๊ฒฝ๋กœ์— `GET` ์ž‘์—…์„ ์ง„ํ–‰ํ•ฉ์‹œ๋‹ค.
๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
```JSON
{
"username": "johndoe",
"email": "[email protected]",
"full_name": "John Doe",
"disabled": false,
"hashed_password": "fakehashedsecret"
}
```
<img src="/img/tutorial/security/image06.png">
์ž ๊ธˆ ์•„์ด์ฝ˜์„ ํด๋ฆญํ•˜๊ณ  ๋กœ๊ทธ์•„์›ƒํ•œ ๋‹ค์Œ ๋™์ผํ•œ ์ž‘์—…์„ ๋‹ค์‹œ ์‹œ๋„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ HTTP 401 ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
```JSON
{
"detail": "Not authenticated"
}
```
### ๋น„ํ™œ์„ฑ๋œ ์œ ์ €
์ด์ œ ๋น„ํ™œ์„ฑ๋œ ์‚ฌ์šฉ์ž๋กœ ์‹œ๋„ํ•˜๊ณ , ์ธ์ฆํ•ด๋ด…์‹œ๋‹ค:
์œ ์ €๋ช…: `alice`
ํŒจ์Šค์›Œ๋“œ: `secret2`
๊ทธ๋ฆฌ๊ณ  `/users/me` ๊ฒฝ๋กœ์™€ ํ•จ๊ป˜ `GET` ์ž‘์—…์„ ์‚ฌ์šฉํ•ด ๋ด…์‹œ๋‹ค.
๋‹ค์Œ๊ณผ ๊ฐ™์€ "Inactive user" ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค:
```JSON
{
"detail": "Inactive user"
}
```
## ์š”์•ฝ
์ด์ œ API์— ๋Œ€ํ•œ `username` ๋ฐ `password`๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์™„์ „ํ•œ ๋ณด์•ˆ ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋Ÿฌํ•œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณด์•ˆ ์‹œ์Šคํ…œ์„ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ๋ชจ๋“  ์‚ฌ์šฉ์ž ๋˜๋Š” ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๊ณผ ํ˜ธํ™˜๋˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์œ ์ผํ•œ ์˜ค์ ์€ ์•„์ง ์‹ค์ œ๋กœ "์•ˆ์ „"ํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋‹ค์Œ ์žฅ์—์„œ๋Š” ์•ˆ์ „ํ•œ ํŒจ์Šค์›Œ๋“œ ํ•ด์‹ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ <abbr title="JSON Web Tokens">JWT</abbr> ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
Loadingโ€ฆ
Cancel
Save