Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Ruxsat klasslari
- 2.2. permission_classes
- 2.3. IsAuthenticatedOrReadOnly
- 2.4. Maxsus ruxsat (obyekt darajasida)
- 2.5. Throttling (so'rov cheklash)
- 2.6. AnonRateThrottle / UserRateThrottle
- 2.7. 429 Too Many Requests
- 2.8. API himoya qatlamlari
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Ruxsat klasslari
- Misol 2 — IsAuthenticatedOrReadOnly va admin
- Misol 3 — Throttling (so'rov cheklash)
- Misol 4 — Amaliy: himoyalangan API (ruxsat + throttle)
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
21.14-dars: Ruxsat va throttling
21-QISM — DJANGO · 14-dars
1. Kirish va motivatsiya
API tayyor (view, serializer), lekin u himoyasiz: har kim har amalni qila oladi, va cheksiz so'rov yubora oladi (server yuki). Bu darsda DRF'ning himoya vositalarini o'rganamiz: ruxsat (permission — kim nima qila oladi) va throttling (so'rov sonini cheklash — rate limiting).
Bu 20.11 dagi ruxsatlar va 20-qismdagi xavfsizlikning DRF versiyasi — lekin tayyor klasslar bilan. IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly — ruxsat klasslari; AnonRateThrottle, UserRateThrottle — so'rov cheklovchilari. Bir necha qator bilan API himoyalanadi.
Real vaziyat. Bir API ochiq edi — har kim ma'lumot o'chira olardi (ruxsatsiz), va bir bot minutiga minglab so'rov yuborib serverni yiqitdi (DoS). Jamoa DRF himoyasini qo'shdi: IsAuthenticated (faqat kirganlar), IsAdminUser (o'chirish — admin), UserRateThrottle (soatiga 100 so'rov). Endi API himoyalangan va cheklangan. DRF ruxsat/throttling — API xavfsizligining tayyor qatlami.
Bu darsda ruxsat va throttlingni — permission klasslari va rate limitingni o'rganamiz.
Bu darsda:
- Ruxsat klasslari (
IsAuthenticated, ...) -
permission_classes IsAuthenticatedOrReadOnly(o'qish ochiq)- Maxsus ruxsat (obyekt darajasida)
- Throttling (so'rov cheklash)
AnonRateThrottle/UserRateThrottle429 Too Many Requests- Amaliy: himoyalangan API
ℹ Misollarda DRF
APIClientbilan sinaladi.
2. Nazariya — chuqur tushuntirish
2.1. Ruxsat klasslari
DRF tayyor ruxsat klasslari beradi:
| Klass | Ruxsat |
|---|---|
AllowAny |
Hamma (ochiq) |
IsAuthenticated |
Faqat kirganlar |
IsAdminUser |
Faqat admin (is_staff) |
IsAuthenticatedOrReadOnly |
O'qish — hamma, yozish — kirganlar |
Ruxsat klasslari — kim view'ga kira olishini belgilaydi 20.11-bob. IsAuthenticated — kirmagan → 403; IsAdminUser — admin bo'lmagan → 403. Bu 20.11 dagi rol/ruxsat tekshiruvining tayyor versiyasi.
2.2. permission_classes
View'ga ruxsat qo'shish:
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import api_view, permission_classes
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def profil(request):
return Response({"ism": request.user.username})
# klassli:
class KursView(APIView):
permission_classes = [IsAuthenticated] permission_classes — view uchun ruxsat klasslari ro'yxati. Funksiyali view'da @permission_classes([...]), klassli view'da permission_classes = [...]. Barcha klasslar o'tishi kerak (VA). Ruxsatsiz → 403.
2.3. IsAuthenticatedOrReadOnly
Ko'p tarqalgan naqsh — o'qish ochiq, yozish himoyalangan:
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class KursViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticatedOrReadOnly]
# GET (o'qish) — hamma; POST/PUT/DELETE (yozish) — kirganlar IsAuthenticatedOrReadOnly — xavfsiz metodlar (GET, HEAD — o'qish, 20.2) hamma uchun; o'zgartiruvchi metodlar (POST, PUT, DELETE — yozish) faqat kirganlar. Bu keng tarqalgan: ma'lumotni hamma ko'radi, faqat kirganlar o'zgartiradi.
2.4. Maxsus ruxsat (obyekt darajasida)
O'z ruxsat klasslaringiz (egalik, 20.11):
from rest_framework.permissions import BasePermission, SAFE_METHODS
class FaqatEgasi(BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in SAFE_METHODS:
return True # o'qish — hamma
return obj.muallif == request.user # yozish — egasi Maxsus ruxsat — BasePermissiondan meros: has_permission (umumiy), has_object_permission (obyekt darajasida — egalik). Bu 20.11 dagi egalik tekshiruvining DRF versiyasi. SAFE_METHODS — o'qish metodlari.
2.5. Throttling (so'rov cheklash)
Throttling — so'rov sonini cheklaydi (rate limiting):
# settings.py:
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_RATES": {
"anon": "100/hour", # anonim
"user": "1000/hour", # kirgan
},
} Throttling — bir foydalanuvchi/IP chekli so'rov yubora oladi (masalan, soatiga 100). Ortiqcha so'rov → 429 Too Many Requests. Bu serverni himoya qiladi (DoS, suiiste'mol) va adolat (bir kishi hammasini band qilmasin).
2.6. AnonRateThrottle / UserRateThrottle
Ikki asosiy throttle:
| Throttle | Kim uchun | Kalit |
|---|---|---|
AnonRateThrottle |
Anonim (kirmagan) | IP manzil |
UserRateThrottle |
Kirgan | Foydalanuvchi ID |
ScopedRateThrottle |
Endpoint bo'yicha | Maxsus |
from rest_framework.throttling import UserRateThrottle
class KursView(APIView):
throttle_classes = [UserRateThrottle] AnonRateThrottle — anonim so'rovlarni IP bo'yicha cheklaydi; UserRateThrottle — kirgan foydalanuvchini ID bo'yicha. Ikkalasi birga (anonim kam, kirgan ko'p). ScopedRateThrottle — muayyan endpoint uchun (masalan, login — kam).
2.7. 429 Too Many Requests
Throttle chegarasi oshsa — 429:
so'rov 1-100: 200 OK
so'rov 101: 429 Too Many Requests (Retry-After: ...) 429 Too Many Requests — throttle chegarasi oshdi. Retry-After sarlavhasi — qachon qayta urinish mumkin. Mijoz buni ko'rib kutadi. Bu 20.6 dagi status kodlarning biri (server himoyasi).
2.8. API himoya qatlamlari
DRF himoya — bir necha qatlam:
| Qatlam | Vazifa |
|---|---|
| Autentifikatsiya | Kim (token/sessiya) |
| Ruxsat | Nima qila oladi |
| Throttling | Qancha so'rov |
| Validatsiya | Ma'lumot to'g'rimi (serializer) |
DRF API himoyasi qatlam-qatlam (20.11, 20.12): autentifikatsiya (kim), ruxsat (nima), throttling (qancha), validatsiya (ma'lumot). Har qatlam bir himoya. Bular birga — xavfsiz, mustahkam API. Hammasi tayyor klasslar bilan.
3. Tez ma'lumotnoma
from rest_framework.permissions import IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly, BasePermission, SAFE_METHODS
from rest_framework.throttling import AnonRateThrottle, UserRateThrottle
from rest_framework.decorators import api_view, permission_classes, throttle_classes
# ruxsat:
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def profil(request): ...
class KursViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticatedOrReadOnly]
throttle_classes = [UserRateThrottle]
# maxsus ruxsat:
class FaqatEgasi(BasePermission):
def has_object_permission(self, request, view, obj):
return request.method in SAFE_METHODS or obj.muallif == request.user
# settings.py:
REST_FRAMEWORK = {"DEFAULT_THROTTLE_RATES": {"anon": "100/hour", "user": "1000/hour"}}Ruxsat/throttle
AllowAny · IsAuthenticated · IsAdminUser · IsAuthenticatedOrReadOnly
AnonRateThrottle · UserRateThrottle · 429 Too Many Requests4. Batafsil misollar
Misollarda DRF
APIClientbilan sinaladi.
Misol 1 — Ruxsat klasslari
"""ruxsat klasslari (AllowAny, IsAuthenticated); permission_classes; kirmagan → 403; kirgan → 200."""
import warnings
warnings.filterwarnings("ignore")
import sys
import tempfile
import types
from io import StringIO
import django
from django.conf import settings
settings.configure(
DEBUG=False,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["django.contrib.contenttypes", "django.contrib.auth", "django.contrib.sessions", "rest_framework", "wisar"],
ROOT_URLCONF=__name__,
ALLOWED_HOSTS=["*"],
SECRET_KEY="namuna",
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
)
_app = types.ModuleType("wisar")
_app.__path__ = [tempfile.gettempdir()]
sys.modules["wisar"] = _app
django.setup()
from django.core.management import call_command
call_command("migrate", stdout=StringIO(), verbosity=0)
from django.contrib.auth.models import User
from django.urls import path
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
@api_view(["GET"])
@permission_classes([AllowAny])
def ochiq(request):
return Response({"xabar": "hamma uchun"})
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def himoyalangan(request):
return Response({"ism": request.user.username})
urlpatterns = [path("ochiq/", ochiq), path("profil/", himoyalangan)]
def main() -> None:
from rest_framework.test import APIClient
client = APIClient()
print("=== 1. Ochiq endpoint (AllowAny) ===")
print(f" /ochiq/ → status {client.get('/ochiq/').status_code}")
print("\n=== 2. ⚠️ Himoyalangan (kirmagan → 403) ===")
print(f" /profil/ (kirmagan) → status {client.get('/profil/').status_code}")
print("\n=== 3. Himoyalangan (kirgach → 200) ===")
ali = User.objects.create_user(username="ali", password="p")
client.force_authenticate(user=ali)
javob = client.get("/profil/")
print(f" /profil/ (kirgan) → status {javob.status_code}, {javob.json()}")
print("\n=== 4. Chiqgach yana himoyalangan ===")
client.force_authenticate(user=None)
print(f" /profil/ (chiqgach) → status {client.get('/profil/').status_code}")
print(" ⭐ permission_classes — IsAuthenticated (kirmagan → 403)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ochiq endpoint (AllowAny) ===
/ochiq/ → status 200
=== 2. ⚠️ Himoyalangan (kirmagan → 403) ===
/profil/ (kirmagan) → status 403
=== 3. Himoyalangan (kirgach → 200) ===
/profil/ (kirgan) → status 200, {'ism': 'ali'}
=== 4. Chiqgach yana himoyalangan ===
/profil/ (chiqgach) → status 403
⭐ permission_classes — IsAuthenticated (kirmagan → 403)Nima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 2 — IsAuthenticatedOrReadOnly va admin
"""IsAuthenticatedOrReadOnly (o'qish ochiq, yozish himoyalangan); IsAdminUser; xavfsiz vs o'zgartiruvchi metod."""
import warnings
warnings.filterwarnings("ignore")
import sys
import tempfile
import types
from io import StringIO
import django
from django.conf import settings
settings.configure(
DEBUG=False,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["django.contrib.contenttypes", "django.contrib.auth", "django.contrib.sessions", "rest_framework", "wisar"],
ROOT_URLCONF=__name__,
ALLOWED_HOSTS=["*"],
SECRET_KEY="namuna",
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
)
_app = types.ModuleType("wisar")
_app.__path__ = [tempfile.gettempdir()]
sys.modules["wisar"] = _app
django.setup()
from django.core.management import call_command
call_command("migrate", stdout=StringIO(), verbosity=0)
from django.contrib.auth.models import User
from django.db import connection, models
from django.urls import include, path
from rest_framework import routers, serializers, viewsets
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class Kurs(models.Model):
nom = models.CharField(max_length=100)
class Meta:
app_label = "wisar"
class KursSerializer(serializers.ModelSerializer):
class Meta:
model = Kurs
fields = ["id", "nom"]
class KursViewSet(viewsets.ModelViewSet):
queryset = Kurs.objects.all()
serializer_class = KursSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
router = routers.SimpleRouter()
router.register("kurslar", KursViewSet)
urlpatterns = [path("api/", include(router.urls))]
def main() -> None:
with connection.schema_editor() as se:
se.create_model(Kurs)
Kurs.objects.create(nom="Python")
from rest_framework.test import APIClient
client = APIClient()
print("=== 1. O'qish ochiq (kirmagan, GET) ===")
print(f" GET /api/kurslar/ → status {client.get('/api/kurslar/').status_code}")
print("\n=== 2. ⚠️ Yozish himoyalangan (kirmagan, POST) ===")
javob = client.post("/api/kurslar/", {"nom": "Go"}, format="json")
print(f" POST (kirmagan) → status {javob.status_code}")
print("\n=== 3. Yozish (kirgach, POST) ===")
ali = User.objects.create_user(username="ali", password="p")
client.force_authenticate(user=ali)
javob = client.post("/api/kurslar/", {"nom": "Go"}, format="json")
print(f" POST (kirgan) → status {javob.status_code}")
print("\n=== 4. O'qish har doim ochiq ===")
client.force_authenticate(user=None)
print(f" GET (chiqgach) → status {client.get('/api/kurslar/').status_code}")
print(" ⭐ IsAuthenticatedOrReadOnly — o'qish hamma, yozish kirganlar")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. O'qish ochiq (kirmagan, GET) ===
GET /api/kurslar/ → status 200
=== 2. ⚠️ Yozish himoyalangan (kirmagan, POST) ===
POST (kirmagan) → status 403
=== 3. Yozish (kirgach, POST) ===
POST (kirgan) → status 201
=== 4. O'qish har doim ochiq ===
GET (chiqgach) → status 200
⭐ IsAuthenticatedOrReadOnly — o'qish hamma, yozish kirganlarNima ko'rsatdi: 2.3-bo'lim.
Misol 3 — Throttling (so'rov cheklash)
"""throttling (so'rov cheklash); AnonRateThrottle; 2/min rate; 429 Too Many Requests; server himoyasi."""
import warnings
warnings.filterwarnings("ignore")
import sys
import tempfile
import types
from io import StringIO
import django
from django.conf import settings
settings.configure(
DEBUG=False,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["django.contrib.contenttypes", "django.contrib.auth", "django.contrib.sessions", "rest_framework", "wisar"],
ROOT_URLCONF=__name__,
ALLOWED_HOSTS=["*"],
SECRET_KEY="namuna",
REST_FRAMEWORK={"DEFAULT_THROTTLE_RATES": {"anon": "3/min"}},
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
)
_app = types.ModuleType("wisar")
_app.__path__ = [tempfile.gettempdir()]
sys.modules["wisar"] = _app
django.setup()
from django.core.management import call_command
call_command("migrate", stdout=StringIO(), verbosity=0)
from django.urls import path
from rest_framework.response import Response
from rest_framework.throttling import AnonRateThrottle
from rest_framework.views import APIView
class CheklanganView(APIView):
throttle_classes = [AnonRateThrottle]
def get(self, request):
return Response({"ok": True})
urlpatterns = [path("cheklangan/", CheklanganView.as_view())]
def main() -> None:
from rest_framework.test import APIClient
client = APIClient()
print("=== 1. Rate cheklovi: 3/min ===")
print(" har anonim IP minutiga 3 so'rov")
print("\n=== 2. So'rovlar (4 marta) ===")
kodlar = [client.get("/cheklangan/").status_code for _ in range(5)]
print(f" status kodlar: {kodlar}")
print("\n=== 3. Chegaradan keyin 429 ===")
print(f" 1-3 so'rov: 200 (ruxsat), 4+: 429 (Too Many Requests)")
print("\n=== 4. Server himoyasi ===")
print(f" 429 soni: {kodlar.count(429)} (chegaradan oshgan)")
print(" ⭐ throttling — so'rov cheklash; 429 (DoS/suiiste'mol himoyasi)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Rate cheklovi: 3/min ===
har anonim IP minutiga 3 so'rov
=== 2. So'rovlar (4 marta) ===
status kodlar: [200, 200, 200, 429, 429]
=== 3. Chegaradan keyin 429 ===
1-3 so'rov: 200 (ruxsat), 4+: 429 (Too Many Requests)
=== 4. Server himoyasi ===
429 soni: 2 (chegaradan oshgan)
⭐ throttling — so'rov cheklash; 429 (DoS/suiiste'mol himoyasi)Nima ko'rsatdi: 2.5, 2.6, 2.7-bo'limlar.
Misol 4 — Amaliy: himoyalangan API (ruxsat + throttle)
Ruxsat va throttlingni birlashtirgan to'liq himoyalangan API: o'qish ochiq, yozish kirganlarga, va so'rov cheklovi. Bu — real DRF API'ning himoya qatlami.
"""to'liq himoya: IsAuthenticatedOrReadOnly + throttling; o'qish ochiq, yozish himoyalangan, cheklangan; qatlamli."""
import warnings
warnings.filterwarnings("ignore")
import sys
import tempfile
import types
from io import StringIO
import django
from django.conf import settings
settings.configure(
DEBUG=False,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["django.contrib.contenttypes", "django.contrib.auth", "django.contrib.sessions", "rest_framework", "wisar"],
ROOT_URLCONF=__name__,
ALLOWED_HOSTS=["*"],
SECRET_KEY="namuna",
REST_FRAMEWORK={"DEFAULT_THROTTLE_RATES": {"user": "100/min", "anon": "50/min"}},
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
)
_app = types.ModuleType("wisar")
_app.__path__ = [tempfile.gettempdir()]
sys.modules["wisar"] = _app
django.setup()
from django.core.management import call_command
call_command("migrate", stdout=StringIO(), verbosity=0)
from django.contrib.auth.models import User
from django.db import connection, models
from django.urls import include, path
from rest_framework import routers, serializers, viewsets
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.throttling import AnonRateThrottle, UserRateThrottle
class Kurs(models.Model):
nom = models.CharField(max_length=100)
class Meta:
app_label = "wisar"
class KursSerializer(serializers.ModelSerializer):
class Meta:
model = Kurs
fields = ["id", "nom"]
class KursViewSet(viewsets.ModelViewSet):
queryset = Kurs.objects.all()
serializer_class = KursSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
throttle_classes = [AnonRateThrottle, UserRateThrottle]
router = routers.SimpleRouter()
router.register("kurslar", KursViewSet)
urlpatterns = [path("api/", include(router.urls))]
def main() -> None:
with connection.schema_editor() as se:
se.create_model(Kurs)
Kurs.objects.create(nom="Python")
from rest_framework.test import APIClient
client = APIClient()
print("=== 1. O'qish (anonim, ochiq) ===")
print(f" GET → status {client.get('/api/kurslar/').status_code}")
print("\n=== 2. ⚠️ Yozish (anonim, taqiq) ===")
print(f" POST (anonim) → status {client.post('/api/kurslar/', {'nom': 'Go'}, format='json').status_code}")
print("\n=== 3. Yozish (kirgan, ruxsat) ===")
ali = User.objects.create_user(username="ali", password="p")
client.force_authenticate(user=ali)
print(f" POST (kirgan) → status {client.post('/api/kurslar/', {'nom': 'Go'}, format='json').status_code}")
print("\n=== 4. Himoya qatlamlari ===")
print(" autentifikatsiya (kim) → ruxsat (nima) → throttle (qancha)")
print(f" jami kurslar: {Kurs.objects.count()}")
print(" ⭐ ruxsat + throttle — qatlamli API himoyasi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. O'qish (anonim, ochiq) ===
GET → status 200
=== 2. ⚠️ Yozish (anonim, taqiq) ===
POST (anonim) → status 403
=== 3. Yozish (kirgan, ruxsat) ===
POST (kirgan) → status 201
=== 4. Himoya qatlamlari ===
autentifikatsiya (kim) → ruxsat (nima) → throttle (qancha)
jami kurslar: 2
⭐ ruxsat + throttle — qatlamli API himoyasiNima ko'rsatdi: 2.1–2.8-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "API himoyasiz bo'lsin" | Ruxsat + throttle |
| "Ruxsatni qo'lda yozish" | Tayyor klasslar |
| "Barcha yoki hech" | IsAuthenticatedOrReadOnly |
| "So'rov cheksiz" | Throttling (rate limit) |
| "Egalik qo'lda har view'da" | Maxsus permission klass |
| "429 — xato" | Throttle (normal himoya) |
| "Anonim va kirgan bir xil limit" | Alohida (anon/user) |
| "Ruxsat = autentifikatsiya" | Kim (auth) vs nima (perm) |
6. Keng tarqalgan xatolar va yechimlari
1. API'ni himoyasiz qoldirish
class KursViewSet(viewsets.ModelViewSet): ... # ⚠️ hamma o'chira oladi
permission_classes = [IsAuthenticatedOrReadOnly] # ✅2. Ruxsatni qo'lda tekshiruv
def get(self, request):
if not request.user.is_authenticated: ... # ⚠️ har view'da
permission_classes = [IsAuthenticated] # ✅3. Throttlingsiz (DoS xavfi)
# throttle yo'q # ⚠️ cheksiz so'rov
throttle_classes = [UserRateThrottle] # ✅4. Anonim va kirganga bir xil limit
"anon": "1000/hour" # ⚠️ anonim ko'p
"anon": "100/hour", "user": "1000/hour" # ✅5. Egalikni umumiy ruxsatda
# has_permission'da egalik # ⚠️ obyekt yo'q
def has_object_permission(self, ...): ... # ✅ obyekt darajasida6. SAFE_METHODSni unutish (maxsus ruxsatda)
return obj.muallif == request.user # ⚠️ o'qish ham taqiq
if request.method in SAFE_METHODS: return True # ✅ o'qish ochiq7. 429ni xato deb qabul qilish
# 429 → xato deb log # ⚠️ normal himoya
# 429 → Retry-After kutish (mijoz) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 20.11-dars (o'tilgan): ruxsatlar — DRF versiyasi
- 21.11-dars (o'tilgan): auth — ruxsat asosi
- 21.12/21.13-dars (o'tilgan): DRF, serializer
- 20.6-dars (o'tilgan): status kodlar —
403,429 - 28-qism: infratuzilma — rate limiting (server darajasida)
8. Eng yaxshi amaliyotlar
API'ni ruxsat klasslari bilan himoyalang.
Tayyor ruxsat klasslarini ishlating (
IsAuthenticated).IsAuthenticatedOrReadOnly— o'qish ochiq, yozish himoyalangan.Egalik uchun maxsus permission (
has_object_permission).Throttling bilan so'rov sonini cheklang (DoS himoyasi).
Anonim va kirganga alohida limit.
SAFE_METHODSbilan o'qishni ochiq qoldiring.429ni normal himoya deb qabul qiling (Retry-After).
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # ruxsat klassi nima?
2. # IsAuthenticated nima?
3. # permission_classes nima?
4. # IsAuthenticatedOrReadOnly nima?
5. # has_object_permission nima?
6. # throttling nima?
7. # AnonRateThrottle nima?
8. # UserRateThrottle nima?
9. # 429 nima?
10. # SAFE_METHODS nima?
11. # ruxsat va auth farqi?
12. # ruxsatsiz status?Javoblar
- Kim view'ga kira olishini belgilaydi
- Faqat kirganlar
- View ruxsat klasslari ro'yxati
- O'qish — hamma, yozish — kirganlar
- Obyekt darajasidagi ruxsat (egalik)
- So'rov sonini cheklash (rate limit)
- Anonim so'rovni IP bo'yicha cheklaydi
- Kirgan foydalanuvchini ID bo'yicha
- Too Many Requests (throttle oshdi)
- O'qish metodlari (GET, HEAD)
- Auth — kim; ruxsat — nima qila oladi
- 403 (Forbidden)
Vazifa 2: Xatolarni tuzating
1. class KursViewSet(viewsets.ModelViewSet): ... # himoya
2. if not request.user.is_authenticated: ... # permission
3. # throttle yo'q # DoS
4. "anon": "1000/hour" # limit
5. return obj.muallif == request.user # SAFEJavoblar
1. permission_classes = [IsAuthenticatedOrReadOnly]
2. permission_classes = [IsAuthenticated]
3. throttle_classes = [UserRateThrottle]
4. "anon": "100/hour", "user": "1000/hour"
5. if request.method in SAFE_METHODS: return True
return obj.muallif == request.userVazifa 3: Himoyalangan API
Ruxsat bilan API:
IsAuthenticated,IsAdminUser,IsAuthenticatedOrReadOnly- Har biri uchun endpoint
- Kirgan/kirmagan test
403holatlari
Vazifa 4: Maxsus ruxsat
Egalik ruxsati:
FaqatEgasipermission klasshas_object_permissionSAFE_METHODS(o'qish ochiq)- Ega/begona test
Vazifa 5: Throttling
So'rov cheklash:
AnonRateThrottle,UserRateThrottle- Turli rate (anon/user)
429holati- Chegara test
Vazifa 6: To'liq himoya
Qatlamli API:
- Auth + ruxsat + throttle
- O'qish/yozish farqi
- Anonim/kirgan/admin
- Har qatlam test
Vazifa 7: O'ylash
DRF ruxsat va throttling — API himoyasini qatlamlarga ajratadi: autentifikatsiya (kim), ruxsat (nima qila oladi), throttling (qancha). Har qatlam bir himoya, va birga ular mustahkam. Bu "chuqurlikda himoya" (defense in depth) tamoyili — bir himoya buzilsa, boshqasi ushlaydi. Xavfsizlikni ko'p qatlamga taqsimlashning afzalligi nima, va nima uchun bitta himoyaga tayanish (masalan, faqat auth) xatarli?
Javob
Qisqa javob: DRF himoya qatlamlarga ajratilgan: auth (kim), ruxsat (nima), throttle (qancha), validatsiya (ma'lumot). Har qatlam bir vazifaga mas'ul, va birga ular mustahkam. "Chuqurlikda himoya" — bir qatlam yetmasa/buzilsa, boshqasi ushlaydi. Ko'p qatlamga taqsimlashning afzalligi: bir nuqta buzilish butun tizimni buzmaydi (auth o'tib ketsa, ruxsat ushlaydi; ruxsat o'tsa, throttle serverni himoya qiladi). Bitta himoyaga tayanish xatarli, chunki u bitta buzilish nuqtasi — u buzilsa, hech nima qolmaydi. Ko'p qatlam — ishonchli (bir xato halokatli emas).
1. Qatlamlar
| Qatlam | Vazifa |
|---|---|
| Autentifikatsiya | Kim (token/sessiya) |
| Ruxsat | Nima qila oladi |
| Throttling | Qancha so'rov |
| Validatsiya | Ma'lumot to'g'rimi |
2. Chuqurlikda himoya
Bir qatlam buzilsa/yetmasa — boshqasi ushlaydi. Himoya takrorlangan (har qatlam mustaqil).
3. Bitta himoya xatarli
Faqat auth bo'lsa — u buzilsa (token o'g'irlansa), hamma narsa ochiq. Bitta buzilish nuqtasi — halokatli. Ko'p qatlam — bir buzilish butun tizimni buzmaydi.
4. "Chuqurlikda himoya" boshqa joyda
| Soha | Qatlamlar |
|---|---|
| DRF | Auth/ruxsat/throttle |
| Tarmoq | Firewall/VPN/shifrlash |
| Kirish | Parol/2FA/qurilma |
| Ma'lumot | Validatsiya/escape/parametr |
5. Muhandislik saboqlari
- Himoyani qatlamlarga taqsimla
- Bir qatlam buzilsa — boshqasi ushlaydi
- Bitta himoya — bitta buzilish nuqtasi (xatarli)
- Chuqurlikda himoya — ishonchli
6. Xulosa
- DRF himoya — qatlamli (auth/ruxsat/throttle)
- Chuqurlikda himoya — takror, mustaqil
- Bitta himoya — halokatli (bir buzilish)
- Ko'p qatlam — bir xato halokatli emas
Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.
Xulosa
Bu darsda DRF ruxsat va throttlingni o'rgandik.
Eng muhim uch fikr:
Ruxsat klasslari. DRF tayyor ruxsat klasslari beradi:
AllowAny(hamma),IsAuthenticated(kirganlar),IsAdminUser(admin),IsAuthenticatedOrReadOnly(o'qish — hamma, yozish — kirganlar).permission_classesbilan view'ga qo'shiladi (funksiyali —@permission_classes([...]), klassli —permission_classes = [...]). Ruxsatsiz →403. Bu 20.11 dagi rol/ruxsat tekshiruvining tayyor versiyasi. Egalik uchun maxsus permission (BasePermission,has_object_permission,SAFE_METHODS).Throttling. Throttling — so'rov sonini cheklaydi (rate limiting):
AnonRateThrottle(anonim, IP bo'yicha),UserRateThrottle(kirgan, ID bo'yicha),ScopedRateThrottle(endpoint).DEFAULT_THROTTLE_RATESbilan sozlanadi ("anon": "100/hour"). Chegara oshsa →429 Too Many Requests(Retry-Afterbilan). Bu serverni DoS/suiiste'moldan himoya qiladi va adolat ta'minlaydi (bir kishi hammasini band qilmasin).Qatlamli himoya. DRF API himoyasi qatlam-qatlam: autentifikatsiya (kim), ruxsat (nima qila oladi), throttling (qancha so'rov), validatsiya (ma'lumot to'g'rimi — serializer). Har qatlam bir himoya, va birga ular mustahkam — bu "chuqurlikda himoya" (defense in depth): bir qatlam buzilsa/yetmasa, boshqasi ushlaydi. Bitta himoyaga tayanish xatarli (bitta buzilish nuqtasi); ko'p qatlam — bir xato halokatli emas. Hammasi tayyor DRF klasslari bilan.
Keyingi darsda signal va middleware ni o'rganamiz: Django'ning hodisa tizimi (signals — model saqlanganda avtomatik amal) va middleware (har so'rov/javobni qayta ishlovchi qatlam).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!