Files
fastapi/docs/tr/docs/advanced/security/http-basic-auth.md
2026-01-31 19:22:34 +00:00

5.5 KiB
Raw Blame History

HTTP Basic Auth

En basit senaryolarda HTTP Basic Auth kullanabilirsiniz.

HTTP Basic Authta uygulama, içinde kullanıcı adı ve şifre bulunan bir header bekler.

Eğer bunu almazsa HTTP 401 "Unauthorized" hatası döndürür.

Ayrıca değeri Basic olan ve isteğe bağlı realm parametresi içerebilen WWW-Authenticate headerını da döndürür.

Bu da tarayıcıya, kullanıcı adı ve şifre için entegre giriş penceresini göstermesini söyler.

Ardından kullanıcı adı ve şifreyi yazdığınızda tarayıcı bunları otomatik olarak header içinde gönderir.

Basit HTTP Basic Auth

  • HTTPBasic ve HTTPBasicCredentials import edin.
  • HTTPBasic kullanarak bir "security scheme" oluşturun.
  • path operationınızda bir dependency ile bu securityyi kullanın.
  • Bu, HTTPBasicCredentials tipinde bir nesne döndürür:
    • İçinde gönderilen username ve password bulunur.

{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}

URLyi ilk kez açmaya çalıştığınızda (veya dokümanlardaki "Execute" butonuna tıkladığınızda) tarayıcı sizden kullanıcı adınızı ve şifrenizi ister:

Kullanıcı adını kontrol edin

Daha kapsamlı bir örneğe bakalım.

Kullanıcı adı ve şifrenin doğru olup olmadığını kontrol etmek için bir dependency kullanın.

Bunun için kullanıcı adı ve şifreyi kontrol ederken Python standart modülü olan secretsi kullanın.

secrets.compare_digest(); bytes ya da yalnızca ASCII karakterleri (İngilizcedeki karakterler) içeren bir str almalıdır. Bu da Sebastián içindeki á gibi karakterlerle çalışmayacağı anlamına gelir.

Bunu yönetmek için önce username ve password değerlerini UTF-8 ile encode ederek bytesa dönüştürürüz.

Sonra secrets.compare_digest() kullanarak credentials.usernamein "stanleyjobson" ve credentials.passwordün "swordfish" olduğundan emin olabiliriz.

{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}

Bu, kabaca şuna benzer olurdu:

if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
    # Return some error
    ...

Ancak secrets.compare_digest() kullanarak, "timing attacks" denilen bir saldırı türüne karşı güvenli olursunuz.

Timing Attacks

Peki "timing attack" nedir?

Bazı saldırganların kullanıcı adı ve şifreyi tahmin etmeye çalıştığını düşünelim.

Ve johndoe kullanıcı adı ve love123 şifresi ile bir request gönderiyorlar.

Uygulamanızdaki Python kodu o zaman kabaca şuna denk olur:

if "johndoe" == "stanleyjobson" and "love123" == "swordfish":
    ...

Ancak Python, johndoe içindeki ilk j ile stanleyjobson içindeki ilk si karşılaştırdığı anda False döndürür; çünkü iki stringin aynı olmadığını zaten anlar ve "kalan harfleri karşılaştırmak için daha fazla hesaplama yapmaya gerek yok" diye düşünür. Uygulamanız da "Incorrect username or password" der.

Sonra saldırganlar bu sefer stanleyjobsox kullanıcı adı ve love123 şifresi ile dener.

Uygulama kodunuz da şuna benzer bir şey yapar:

if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
    ...

Bu kez Python, iki stringin aynı olmadığını fark etmeden önce hem stanleyjobsox hem de stanleyjobson içinde stanleyjobso kısmının tamamını karşılaştırmak zorunda kalır. Bu nedenle "Incorrect username or password" yanıtını vermesi birkaç mikro saniye daha uzun sürer.

Yanıt süresi saldırganlara yardımcı olur

Bu noktada saldırganlar, serverın "Incorrect username or password" responseunu göndermesinin birkaç mikro saniye daha uzun sürdüğünü fark ederek bir şeyleri doğru yaptıklarını anlar; yani başlangıçtaki bazı harfler doğrudur.

Sonra tekrar denerken, bunun johndoedan ziyade stanleyjobsoxa daha yakın bir şey olması gerektiğini bilerek devam edebilirler.

"Profesyonel" bir saldırı

Elbette saldırganlar bunu elle tek tek denemez; bunu yapan bir program yazarlar. Muhtemelen saniyede binlerce ya da milyonlarca test yaparlar ve her seferinde yalnızca bir doğru harf daha elde ederler.

Böylece birkaç dakika ya da birkaç saat içinde doğru kullanıcı adı ve şifreyi, yanıt süresini kullanarak ve uygulamamızın "yardımıyla" tahmin etmiş olurlar.

secrets.compare_digest() ile düzeltin

Ancak bizim kodumuzda secrets.compare_digest() kullanıyoruz.

Kısacası, stanleyjobsox ile stanleyjobsonu karşılaştırmak için geçen süre, johndoe ile stanleyjobsonu karşılaştırmak için geçen süreyle aynı olur. Şifre için de aynı şekilde.

Bu sayede uygulama kodunuzda secrets.compare_digest() kullanarak bu güvenlik saldırıları ailesine karşı güvenli olursunuz.

Hatayı döndürün

Credentialların hatalı olduğunu tespit ettikten sonra, 401 status code ile (credential verilmediğinde dönenle aynı) bir HTTPException döndürün ve tarayıcının giriş penceresini yeniden göstermesi için WWW-Authenticate headerını ekleyin:

{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}