FastAPI OAuth2 avtentifikatsiyasini o'zlashtiring! Ushbu qo'llanma parol, yashirin, avtorizatsiya kodi oqimlari, tokenni yangilash va mustahkam API'lar yaratish uchun xavfsizlikning eng yaxshi amaliyotlarini qamrab oladi.
FastAPI OAuth2 Ilovasini Qoshish: To'liq Avtentifikatsiya Oqimi Qo'llanmasi
Bugungi raqamli landshaftda API'laringizni himoyalash eng muhimdir. OAuth2 (Open Authorization) delegatsiyalangan avtorizatsiya uchun sanoat standarti bo'lib, foydalanuvchilarga o'zlarining ma'lumotlarini baham ko'rmasdan o'z resurslariga cheklangan kirishni berish imkonini beradi. FastAPI, zamonaviy, yuqori samarali Python veb-ramkasi, OAuth2 avtentifikatsiyasini amalga oshirishni osonlashtiradi. Ushbu keng qamrovli qo'llanma sizni turli OAuth2 oqimlari orqali olib boradi va ularni FastAPI ilovangizga qanday integratsiya qilishni namoyish etadi, API'laringiz xavfsiz va ochiq qolishini ta'minlaydi.
OAuth2 Konseptlarini Tushunish
Kodga sho'ng'ishdan oldin, keling, asosiy OAuth2 kontseptlarini aniq tushuntirib beraylik:
- Resurs Egasi: Ma'lumotlar egasi va kirishni beruvchi foydalanuvchi.
- Mijoz: Resurs egasi ma'lumotlariga kirishni so'rayotgan ilova. Bu veb-ilova, mobil ilova yoki boshqa xizmat bo'lishi mumkin.
- Avtorizatsiya Serveri: Resurs egasi avtentifikatsiyasini amalga oshiradi va mijozga avtorizatsiya beradi.
- Resurs Serveri: Himoyalangan resurslarni joylashtiradi va kirishni berishdan oldin kirish tokenini tasdiqlaydi.
- Kirish Tokeni: Mijozga resurs egasi tomonidan berilgan avtorizatsiyani ifodalovchi vosita.
- Yangilash Tokeni: Foydalanuvchidan qayta avtorizatsiya qilishni talab qilmasdan yangi kirish tokenlarini olish uchun ishlatiladigan uzoq muddatli vosita.
- So'rovlar (Scopes): Mijoz so'rayotgan aniq ruxsatnomalarni aniqlaydi.
OAuth2 Oqimlari: To'g'ri Yondashuvni Tanlash
OAuth2 bir nechta avtorizatsiya oqimlarini belgilaydi, har biri turli stsenariylar uchun mos keladi. Mana eng keng tarqalgan oqimlar va ularni qachon ishlatish kerakligi:
1. Parol (Resurs Egasi Parol Kredensiallari) Oqimi
Tavsif: Mijoz foydalanuvchi nomi va parolini taqdim etish orqali to'g'ridan-to'g'ri avtorizatsiya serveridan kirish tokenini oladi. Foydalanish Hali: Juda ishonchli ilovalar, masalan, birinchi tomon mobil ilovalar. Agar boshqa oqimlar mumkin bo'lmasa, faqat undan foydalanish kerak. Afzalliklari: Amalga oshirish oson. Kamchiliklari: Mijoz resurs egasi ma'lumotlarini boshqarishi kerak, bu mijoz buzilgan bo'lsa, ular ochib qo'yish xavfini oshiradi. Boshqa oqimlardan kamroq xavfsiz. Misol: Kompaniyaga tegishli mobil ilova o'zining ichki API'siga kirish.
FastAPI'da Amalga Oshirish:
Avvalo, zarur paketlarni o'rnating:
pip install fastapi uvicorn python-multipart passlib[bcrypt] python-jose[cryptography]
Endi, asosiy misol yaratamiz:
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta
app = FastAPI()
# Kuchli, tasodifiy ravishda yaratilgan maxfiy kalit bilan almashtiring
SECRET_KEY = "YOUR_SECRET_KEY"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# Parolni shifrlash sozlamalari
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# Tasodifiy foydalanuvchi bazasi (ishlab chiqarishda haqiqiy bazaga almashtiring)
users = {
"johndoe": {
"username": "johndoe",
"hashed_password": pwd_context.hash("password123"),
"scopes": ["read", "write"]
}
}
# Parolni tasdiqlash funksiyasi
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
# Kirish tokenini yaratish funksiyasi
def create_access_token(data: dict, expires_delta: timedelta):
to_encode = data.copy()
expire = datetime.utcnow() + expires_delta
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# Token yaratish uchun OAuth2 oxirgi nuqtasi
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = users.get(form_data.username)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Noto'g'ri foydalanuvchi nomi yoki parol",
headers={"WWW-Authenticate": "Bearer"},
)
if not verify_password(form_data.password, user["hashed_password"]):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Noto'g'ri foydalanuvchi nomi yoki parol",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user["username"], "scopes": user["scopes"]},
expires_delta=access_token_expires,
)
return {"access_token": access_token, "token_type": "bearer"}
# So'rovlarni tasdiqlash uchun vosita
async def get_current_user(token: str):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Kredensiallarni tasdiqlash mumkin emas",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = users.get(username)
if user is None:
raise credentials_exception
return user
async def get_current_active_user(current_user = Depends(get_current_user)):
return current_user
# Namuna himoyalangan oxirgi nuqta
@app.get("/users/me")
async def read_users_me(current_user = Depends(get_current_active_user)):
return {"username": current_user["username"], "scopes": current_user["scopes"]}
Tushuntirish:
- Vositalar: Nom va parolni boshqarish uchun `fastapi.security.OAuth2PasswordRequestForm` dan foydalaniladi.
- Parolni Shifrlash: `passlib` parollarni xavfsiz shifrlash va tasdiqlash uchun ishlatiladi. Aslida hech qachon parollarni oddiy matn ko'rinishida saqlamang!
- JWT Yaratish: `python-jose` JSON Veb Tokenlarini (JWT) yaratish va tasdiqlash uchun ishlatiladi.
- `/token` Oxirgi Nuqta: Ushbu oxirgi nuqta kirish jarayonini boshqaradi. U foydalanuvchi nomi va parolni tasdiqlaydi va agar ular to'g'ri bo'lsa, kirish tokenini yaratadi.
- `get_current_user` Vositasi: Ushbu funksiya kirish tokenini tasdiqlaydi va foydalanuvchini oladi.
- `/users/me` Oxirgi Nuqta: Bu himoyalangan oxirgi nuqta bo'lib, kirish uchun to'g'ri kirish tokenini talab qiladi.
2. Yashirin Oqim
Tavsif: Mijoz avtorizatsiya serverida foydalanuvchi avtentifikatsiyasidan so'ng to'g'ridan-to'g'ri kirish tokenini oladi. Kirish tokeni URL fragmentida qaytariladi. Foydalanish Hali: Yashirin kalitlarni saqlash maqsadga muvofiq bo'lmagan bir sahifali ilovalar (SPA) va boshqa brauzerga asoslangan ilovalar. Afzalliklari: Brauzerga asoslangan ilovalar uchun sodda. Kamchiliklari: Kirish tokeni URL'da ochilganligi sababli boshqa oqimlardan kamroq xavfsiz. Yangilash tokeni berilmaydi. Misol: Ijtimoiy tarmoq API'siga kirish uchun JavaScript ilovasi.
FastAPI'da Amalga Oshirish Qaydnomalari:
FastAPI yashirin oqimning (asosan backend ramkasi bo'lganligi sababli) oldingi qismini to'g'ridan-to'g'ri boshqarmaydi, siz React, Vue yoki Angular kabi oldingi qism ramkasidan foydalanib avtentifikatsiya oqimini boshqarasiz. FastAPI asosan Resurs Serveri vazifasini bajaradi.
Soddalashtirilgan Backend (FastAPI - Resurs Serveri) Misol:
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2AuthorizationCodeBearer
from jose import JWTError, jwt
app = FastAPI()
# Kuchli, tasodifiy ravishda yaratilgan maxfiy kalit bilan almashtiring
SECRET_KEY = "YOUR_SECRET_KEY"
ALGORITHM = "HS256"
# Tasodifiy foydalanuvchi bazasi (ishlab chiqarishda haqiqiy bazaga almashtiring)
users = {
"johndoe": {
"username": "johndoe",
"scopes": ["read", "write"]
}
}
# OAuth2 sxemasi - token tasdiqlash uchun AuthorizationCodeBearer dan foydalanish
oauth2_scheme = OAuth2AuthorizationCodeBearer(authorizationUrl="/auth", tokenUrl="/token") # Ushbu URL'lar Avtorizatsiya Serveri tomonidan boshqariladi (bu FastAPI ilovasi emas).
# So'rovlarni tasdiqlash uchun vosita
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Kredensiallarni tasdiqlash mumkin emas",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = users.get(username)
if user is None:
raise credentials_exception
return user
async def get_current_active_user(current_user = Depends(get_current_user)):
return current_user
# Namuna himoyalangan oxirgi nuqta
@app.get("/users/me")
async def read_users_me(current_user = Depends(get_current_active_user)):
return {"username": current_user["username"], "scopes": current_user["scopes"]}
FastAPI bilan Yashirin Oqim uchun Asosiy Qaydnomalar:
- Avtorizatsiya Serverining Vazifasi: Haqiqiy avtorizatsiya va token berish alohida Avtorizatsiya Serverida sodir bo'ladi. FastAPI Resurs Serveri vazifasini bajaradi, tokenni tasdiqlaydi.
- Oldingi Qism Boshqaruvi: Oldingi qism ilovasi (masalan, React, Vue) Avtorizatsiya Serveriga yo'naltirish, foydalanuvchi kirishini va URL fragmentidan kirish tokenini olishni boshqaradi.
- Xavfsizlik Qaydnomalari: Tokenning URL'da ochilganligi sababli, HTTPS dan foydalanish va tokenning amal qilish muddatini qisqa tutish muhim. Yashirin oqimdan, agar imkon bo'lsa, PKCE bilan Avtorizatsiya Kodu Oqimi foydasiga voz kechish kerak.
3. Avtorizatsiya Kodu Oqimi
Tavsif: Mijoz avval avtorizatsiya serveridan avtorizatsiya kodini oladi, keyin uni kirish tokeniga almashtiradi. Ushbu oqim mijozdan avtorizatsiya serveriga va orqaga qaytishni o'z ichiga oladi. Foydalanish Hali: Mijoz siri xavfsiz saqlanadigan veb-ilovalari va mobil ilovalari. Afzalliklari: Yashirin oqimdan ko'ra xavfsizroq, chunki kirish tokeni to'g'ridan-to'g'ri brauzerda ochilmaydi. Kamchiliklari: Yashirin oqimdan ko'ra amalga oshirish murakkabroq. Misol: Foydalanuvchining Google Drive ma'lumotlariga kirishni so'ragan uchinchi tomon ilovasi.
PKCE (Kod Almashinish Kuchi) bilan Avtorizatsiya Kodu Oqimi:
PKCE - bu avtorizatsiya kodining qabul qilinishi xavfini kamaytiradigan Avtorizatsiya Kodu Oqimining kengaytmasi. Bu mobil ilovalari va SPA'lari uchun juda tavsiya etiladi, chunki u mijozning sirni saqlashini talab qilmaydi.
FastAPI'da Amalga Oshirish Qaydnomalari: Yashirin oqimga o'xshash tarzda, FastAPI ushbu oqimda asosan Resurs Serveri vazifasini bajaradi. Avtorizatsiya kodi berish uchun alohida Avtorizatsiya Serveri javobgar.
Soddalashtirilgan Backend (FastAPI - Resurs Serveri) Misol (Yashirin Oqimga O'xshash):
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2AuthorizationCodeBearer
from jose import JWTError, jwt
app = FastAPI()
# Kuchli, tasodifiy ravishda yaratilgan maxfiy kalit bilan almashtiring
SECRET_KEY = "YOUR_SECRET_KEY"
ALGORITHM = "HS256"
# Tasodifiy foydalanuvchi bazasi (ishlab chiqarishda haqiqiy bazaga almashtiring)
users = {
"johndoe": {
"username": "johndoe",
"scopes": ["read", "write"]
}
}
# OAuth2 sxemasi - token tasdiqlash uchun AuthorizationCodeBearer dan foydalanish
oauth2_scheme = OAuth2AuthorizationCodeBearer(authorizationUrl="/auth", tokenUrl="/token") # Ushbu URL'lar Avtorizatsiya Serveri tomonidan boshqariladi.
# So'rovlarni tasdiqlash uchun vosita
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Kredensiallarni tasdiqlash mumkin emas",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = users.get(username)
if user is None:
raise credentials_exception
return user
async def get_current_active_user(current_user = Depends(get_current_user)):
return current_user
# Namuna himoyalangan oxirgi nuqta
@app.get("/users/me")
async def read_users_me(current_user = Depends(get_current_active_user)):
return {"username": current_user["username"], "scopes": current_user["scopes"]}
PKCE bilan Avtorizatsiya Kodu Oqimi uchun Asosiy Qaydnomalar:
- Avtorizatsiya Serverining Vazifasi: Avtorizatsiya Serveri avtorizatsiya kodini yaratish, PKCE kod tekshiruvchisini tasdiqlash va kirish tokenini berishni boshqaradi.
- Oldingi Qism Boshqaruvi: Oldingi qism ilovasi kod tekshiruvchisi va kodning qiyinchiligini yaratadi, foydalanuvchini Avtorizatsiya Serveriga yo'naltiradi, avtorizatsiya kodini oladi va kirish tokeniga almashtiradi.
- Kengaytirilgan Xavfsizlik: PKCE avtorizatsiya kodini qabul qilish hujumlarini oldini oladi, bu SPA'lar va mobil ilovalar uchun mos keladi.
- Tavsiya etilgan Yondashuv: Avtorizatsiya Kodu Oqimi PKCE bilan umuman eng xavfsiz va zamonaviy veb va mobil ilovalar uchun tavsiya etilgan oqimdir.
4. Mijoz Kredensiallari Oqimi
Tavsif: Mijoz o'zining kredensiallari (mijoz ID va mijoz siri) yordamida to'g'ridan-to'g'ri avtorizatsiya serveri bilan avtentifikatsiya qilib, kirish tokenini oladi. Foydalanish Hali: Mashinadan-mashinaga aloqa, masalan, backend xizmatlari bir-biriga kirish. Afzalliklari: Backend xizmatlari uchun sodda. Kamchiliklari: Foydalanuvchi avtentifikatsiyasi uchun mos emas. Misol: Ma'lumotlar bazasi xizmatiga kirish uchun ma'lumotlarni qayta ishlovchi xizmat.
FastAPI'da Amalga Oshirish:
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from jose import JWTError, jwt
from datetime import datetime, timedelta
app = FastAPI()
# Kuchli, tasodifiy ravishda yaratilgan maxfiy kalit bilan almashtiring
SECRET_KEY = "YOUR_SECRET_KEY"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# Tasodifiy mijoz bazasi (ishlab chiqarishda haqiqiy bazaga almashtiring)
clients = {
"client_id": {
"client_secret": "client_secret",
"scopes": ["read", "write"]
}
}
# Kirish tokenini yaratish funksiyasi
def create_access_token(data: dict, expires_delta: timedelta):
to_encode = data.copy()
expire = datetime.utcnow() + expires_delta
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# HTTP Asosiy Avtentifikatsiya sxemasi
security = HTTPBasic()
# Token yaratish uchun oxirgi nuqta
@app.post("/token")
async def login(credentials: HTTPBasicCredentials = Depends(security)):
client = clients.get(credentials.username)
if not client:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Noto'g'ri mijoz ID yoki sir",
headers={"WWW-Authenticate": "Basic"},
)
if credentials.password != client["client_secret"]:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Noto'g'ri mijoz ID yoki sir",
headers={"WWW-Authenticate": "Basic"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": credentials.username, "scopes": client["scopes"]},
expires_delta=access_token_expires,
)
return {"access_token": access_token, "token_type": "bearer"}
# So'rovlarni tasdiqlash uchun vosita
async def get_current_client(token: str):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Kredensiallarni tasdiqlash mumkin emas",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
client_id: str = payload.get("sub")
if client_id is None:
raise credentials_exception
except JWTError:
raise credentials_exception
client = clients.get(client_id)
if client is None:
raise credentials_exception
return client
async def get_current_active_client(current_client = Depends(get_current_client)):
return current_client
# Namuna himoyalangan oxirgi nuqta
@app.get("/data")
async def read_data(current_client = Depends(get_current_active_client)):
return {"message": "Mijoz tomonidan kirilgan ma'lumotlar: " + current_client["client_secret"]}
Tushuntirish:
- HTTP Asosiy Avtentifikatsiyasi: Mijozni avtentifikatsiya qilish uchun `fastapi.security.HTTPBasic` dan foydalaniladi.
- `/token` Oxirgi Nuqta: Ushbu oxirgi nuqta mijoz avtentifikatsiyasini boshqaradi. U mijoz ID va sirni tasdiqlaydi va agar to'g'ri bo'lsa, kirish tokenini yaratadi.
- `get_current_client` Vositasi: Ushbu funksiya kirish tokenini tasdiqlaydi va mijozni oladi.
- `/data` Oxirgi Nuqta: Bu himoyalangan oxirgi nuqta bo'lib, kirish uchun to'g'ri kirish tokenini talab qiladi.
Tokenni Yangilash
Kirish tokenlari odatda buzilgan tokenlar ta'sirini kamaytirish uchun qisqa muddatli amal qilish muddatiga ega. Yangilash tokenlari - bu foydalanuvchidan qayta avtorizatsiya qilishni talab qilmasdan yangi kirish tokenlarini olish uchun ishlatilishi mumkin bo'lgan uzoq muddatli vositalar.
Amalga Oshirish Qaydnomalari:
- Yangilash Tokenlarini Saqlash: Yangilash tokenlari xavfsiz saqlanishi kerak, afzalroq shifrlangan holda ma'lumotlar bazasida.
- Yangilash Tokeni Oxirgi Nuqtasi: Yangilash tokeni so'rovlarini boshqarish uchun maxsus oxirgi nuqta (masalan, `/refresh_token`) yarating.
- Yangilash Tokenlarini Bekor Qilish: Agar ular buzilgan bo'lsa yoki endi kerak bo'lmasa, yangilash tokenlarini bekor qilish mexanizmini amalga oshiring.
Misol (Parol Oqimi Misolini Kengaytirish):
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta
import secrets # Xavfsiz tasodifiy qatorlar yaratish uchun
app = FastAPI()
# Kuchli, tasodifiy ravishda yaratilgan maxfiy kalit bilan almashtiring
SECRET_KEY = "YOUR_SECRET_KEY"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
REFRESH_TOKEN_EXPIRE_DAYS = 30 # Yangilash tokenlari uchun uzoqroq amal qilish muddati
# Parolni shifrlash sozlamalari
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# Tasodifiy foydalanuvchi bazasi (ishlab chiqarishda haqiqiy bazaga almashtiring)
users = {
"johndoe": {
"username": "johndoe",
"hashed_password": pwd_context.hash("password123"),
"scopes": ["read", "write"],
"refresh_token": None # Yangilash tokenini shu yerda saqlang
}
}
# Parolni tasdiqlash funksiyasi (oldingisidek)
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
# Kirish tokenini yaratish funksiyasi (oldingisidek)
def create_access_token(data: dict, expires_delta: timedelta):
to_encode = data.copy()
expire = datetime.utcnow() + expires_delta
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# Yangilash tokenini yaratish funksiyasi
def create_refresh_token():
return secrets.token_urlsafe(32) # Xavfsiz tasodifiy qator yarating
# Token yaratish uchun OAuth2 oxirgi nuqtasi
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = users.get(form_data.username)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Noto'g'ri foydalanuvchi nomi yoki parol",
headers={"WWW-Authenticate": "Bearer"},
)
if not verify_password(form_data.password, user["hashed_password"]):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Noto'g'ri foydalanuvchi nomi yoki parol",
headers={"WWW-Authenticate": "Bearer"},
)
# Yangilash tokenini yarating va saqlang (haqiqiy dunyoda xavfsiz tarzda ma'lumotlar bazasida)
refresh_token = create_refresh_token()
user["refresh_token"] = refresh_token # Hozirda foydalanuvchi ob'ektiga saqlang (ishlab chiqarish uchun XAVFSIZ EMAS)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user["username"], "scopes": user["scopes"]},
expires_delta=access_token_expires,
)
return {"access_token": access_token, "token_type": "bearer", "refresh_token": refresh_token}
# Kirish tokenini yangilash uchun oxirgi nuqta
@app.post("/refresh_token")
async def refresh_access_token(refresh_token: str):
# Yangilash tokeni orqali foydalanuvchini toping (xavfsiz tarzda ma'lumotlar bazasini so'rang)
user = next((user for user in users.values() if user["refresh_token"] == refresh_token), None)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Noto'g'ri yangilash tokeni",
headers={"WWW-Authenticate": "Bearer"},
)
# Yangi kirish tokenini yarating
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user["username"], "scopes": user["scopes"]},
expires_delta=access_token_expires,
)
return {"access_token": access_token, "token_type": "bearer"}
# So'rovlarni tasdiqlash uchun vosita (oldingisidek)
async def get_current_user(token: str):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Kredensiallarni tasdiqlash mumkin emas",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = next((user for user in users.values() if user["username"] == username), None)
if user is None:
raise credentials_exception
return user
async def get_current_active_user(current_user = Depends(get_current_user)):
return current_user
# Namuna himoyalangan oxirgi nuqta (oldingisidek)
@app.get("/users/me")
async def read_users_me(current_user = Depends(get_current_active_user)):
return {"username": current_user["username"], "scopes": current_user["scopes"]}
Muhim Xavfsizlik Qaydnomalari:
- Yangilash Tokenlarini Saqlash: Misolda yangilash tokeni xotirada (xavfsiz emas) saqlanadi. Ishlab chiqarish muhitida, yangilash tokenlarini xavfsiz tarzda ma'lumotlar bazasida saqlang, afzalroq shifrlangan holda.
- Yangilash Tokeni Aylanishi: Yangilash tokeni aylanishini amalga oshirishni ko'rib chiqing. Yangilash tokeni ishlatilgandan so'ng, yangi yangilash tokenini yarating va eskisini bekor qiling. Bu buzilgan yangilash tokenlarining ta'sirini cheklaydi.
- Audit: Shubhali faoliyatni aniqlash uchun yangilash tokeni ishlatilishini qayd qiling.
Xavfsizlikning Eng yaxshi Amaliyotlari
OAuth2 ni amalga oshirish faqat birinchi qadamdir. API'laringizni va foydalanuvchi ma'lumotlarini himoya qilish uchun xavfsizlikning eng yaxshi amaliyotlariga rioya qilish juda muhim.
- HTTPS dan Foydalaning: Mijoz, avtorizatsiya serveri va resurs serveri o'rtasidagi aloqani shifrlash uchun har doim HTTPS dan foydalaning.
- Kirishni Tasdiqlang: Kiritish hujumlarini oldini olish uchun barcha kirish ma'lumotlarini to'liq tasdiqlang.
- Cheklash Tezligi: Brutal kuch hujumlarini oldini olish uchun cheklash tezligini amalga oshiring.
- Depandensiyalarni Muntazam Yangilang: Xavfsizlik zaifliklarini tuzatish uchun FastAPI framework'ingizni va barcha depandensiyalarni yangilab turing.
- Kuchli Maxfiylardan Foydalaning: Mijoz sirlari va JWT imzolash kalitlari uchun kuchli, tasodifiy maxfiylarni yarating. Ushbu maxfiylarni xavfsiz saqlang (masalan, muhit o'zgaruvchilari yoki sirni boshqarish tizimidan foydalanib).
- Kuzatib Boring va Qayd qiling: Shubhali faoliyat uchun API'ngizni kuzatib boring va barcha avtentifikatsiya va avtorizatsiya hodisalarini qayd qiling.
- Eng Kam Ruxsatnomani Qat'iy Bajaring: Mijozlarga faqat zarur ruxsatnomalarni (so'rovlar) bering.
- To'g'ri Xatoliklarni Boshqarish: Xatolik xabarlarida sezgir ma'lumotlarni ochib qo'yishdan saqlaning.
- Yaxshi Sinovdan O'tgan OAuth2 Kutubxonasidan Foydalanishni Ko'rib Chiqing: OAuth2 ni noldan amalga oshirish o'rniga, Authlib kabi yaxshi sinovdan o'tgan kutubxonadan foydalanishni ko'rib chiqing. Authlib OAuth2 ning yanada mustahkam va xavfsizroq amalga oshirilishini ta'minlaydi.
Asoslardan Tashqari: Kengaytirilgan Qaydnomalar
Asosiy OAuth2 amalga oshirilishi o'rnatilgandan so'ng, ushbu kengaytirilgan mavzularni ko'rib chiqing:
- Rozilikni Boshqarish: Foydalanuvchilarga mijozlarga bergan ruxsatnomalarini aniq va granulali nazorat qilishni ta'minlang.
- Delegatsiyalangan Avtorizatsiya: Foydalanuvchilarga ular nomidan harakat qilish uchun mijozlarni avtorizatsiya qilish imkonini beradigan delegatsiyalangan avtorizatsiyani amalga oshiring.
- Ko'p Faktorli Avtentifikatsiya (MFA): Xavfsizlikni oshirish uchun MFA ni integratsiya qiling.
- Federativ Identifikatsiya: Uchinchi tomon identifikatsiya provayderlari (masalan, Google, Facebook, Twitter) orqali avtentifikatsiyani qo'llab-quvvatlang.
- Dinamik Mijoz Ro'yxatdan O'tkazish: Mijozlarga avtorizatsiya serveringizga dinamik ravishda ro'yxatdan o'tishlariga ruxsat bering.
Xulosa
FastAPI bilan OAuth2 avtentifikatsiyasini amalga oshirish API'laringizni himoyalash va foydalanuvchi ma'lumotlarini himoya qilishning kuchli usulidir. Turli OAuth2 oqimlarini tushunish, xavfsizlikning eng yaxshi amaliyotlarini amalga oshirish va kengaytirilgan mavzularni ko'rib chiqish orqali siz foydalanuvchilar va ilovalaringizning ehtiyojlarini qondiradigan mustahkam va xavfsiz API'lar yaratishingiz mumkin. Har bir aniq hol uchun mos oqimni tanlang, xavfsizlikka ustunlik bering va avtentifikatsiya tizimingizni doimiy ravishda kuzatib boring va yaxshilang. Taqdim etilgan misollar asosiy tamoyillarni ko'rsatgan bo'lsa-da, ularni har doim o'zingizning aniq talablaringizga moslashtiring va keng qamrovli ko'rib chiqish uchun xavfsizlik mutaxassislariga murojaat qiling.