Bu yazı RESTFul Api Tasarım İncelikleri serisinin bir parçası niteliğindedir. Eğer okumadıysanız önce serinin diğer yazılarını okumanızı tavsiye ederim.
- REST Api Temelleri
- REST API Çıktı Formatı Ne Olmalı?
- REST API URI yapısı nasıl olmalı?
- REST Api HATEOAS kavramı nedir? (Bu diziye sonradan eklendi)
- REST API kimlik doğrulama nasıl yapılır? (Authentication)
- REST API hata yönetimi nasıl yapılır? (Error Handling)
- REST API güvenliği nasıl sağlanır? (Security)
- REST API Dokümantasyon (Documentation) ve Test’i nasıl yapılır?
- Örnek REST API Projesi
Bu yazı dizisi ve muhtemel sorular hakkında
Bu yazı dizisine başlarken bu kadar zor olacağını tahmin etmiyordum. Sadece tek bir yazı olarak başlamışken, bir yazı dizisine dönüştürmem gerektiğini farkettim, fakat yazmaya devam ettikçe bunun aslında kitap yazılacak bir konu olduğunu görüyorum. Basitleştirmeye çalıştıkça bilgi yetersiz kalırken, detaya girdikçe de konu dallanıp budaklanıyor ve karmaşık hale geliyor.
Konuya iyi bir Rest Api uygulamasının Stateless olması gerektiğini söyleyerek başlayacaktım, sonra kendi kendime “iyi ama önce stateless ne demek bunu açıklamak gerekir” dedim. Konuyu hem dağıtmadan, hem de eksik nokta bırakmadan anlatmak çok güç. Bu nedenle eksik bulduğunuz noktalar veya sorularınız olursa lütfen sosyal medyadan bana ulaşın.
STATEFUL ve STATELESS ne demek?
Stateless tanımını anlatmanın en iyi yolu Statefull nedir onu anlatmak olacak. (Bu tanımlar için anlaşılır Türkçe karşılık bulamadım). Aslında her iki tanım da “state” kelimesinden geliyor.
Stateful ve stateless terimleri sadece Rest Api veya yazılım değil, DevOps ve sunucu sistemleri için de önemli bir bilgi.
State bir sistemin veya koşulun belirli bir andaki durumunu tanımlıyor. (Zaten state kelimesinin Türkçe karşılığı da durum). Örneğin odanızdaki lambanın iki state’i var, açık ya da kapalı. Bu lambayı kontrol eden bir kod’un stateless olması için lambanın herhangi bir andaki durumunu bilmiyor olması gerekir. Stateful bir sistem ise tam tersi herhangi bir anda lamba açık mı kapalı mı bunu bilir.
Sanal bir sistem kuralım. Bu sistemde herkesin kendine ait bir odası olsun. Yüz binlerce kişi canı istediği zaman odasının ışığını açsın veya kapatsın. Sistemi stateless kurarsak sunucu herhangi bir odanın ışığı o anda açık mı kapalı mı bilmeyecektir. Her istemci kendi odasının son durumunu bilmekten sorumludur. Sunucuya ışığı aç veya ışığı kapat isteği gönderir. Böylece sunucu tarafında yüzbinlerce odanın ışığı açık mı/kapalı mı takip etmeyiz. Aksi durumda bu bilgiyi tutmak zorunda olduğumuz gibi, ne zaman gereksiz hale geldiğini de bilemeyiz.
Yazıyı stateless ve stateful konulu bir yazıya çevirmemek için daha fazla uzatmak istemiyorum ama (istisnalar hariç) çoğu zaman stateless bir inşa etmek (eğer mümkünse) daha sorunsuz ve doğru bir çözüm olacaktır.
REST API’nin Stateless olması ne demek?
iyi bir REST API tanım gereği stateless olmalı ve sunucu tarafında bir oturum bilgisi tutmamalıdır. Bir isteğin anlaşılması ve doğrulanması için gereken tüm bilgi istemci tarafından sunucuya gönderilmelidir. Bu sınırlama sunucu tarafında bir bilgi olmayacağı veya o işlem için kullanılan tüm bilginin istemci tarafından gönderileceği anlamına gelmez. Ama sunucu oturum veya bir önceki durumla ilgili bir bilgiyi tutmaz.
Bunu daha rahat anlamak için sayfalama örneğini düşünebiliriz. İstemci bir sorgu gönderecekse o sorgunun kaçıncı sayfasını istediğini belirtmelidir. Sunucu tarafında bir önceki istekte 5. sayfa verilmişti, şimdi sıra 6. sayfada bilgisi tutulmaz.
Öte yandan sunucu tarafında o anki bağlantının 123 ID’li kullanıcıdan geldiği de tutulmaz. Sunucu kendisine gelen isteğin 123 ID’li kullanıcıdan geldiğini isteğin kendisinden tespit edebilmelidir. Peki nasıl?
Sonunda geldik kimlik doğrulama kısmına
Gerekli/gereksiz bir sürü bilginin ardından geldik kimlik doğrulamayı nasıl yapacağımıza, gönderdiğimiz istekte ben “ID=123” veya “username=evrenbal” nasıl diyeceğimize. Bu tabii ki genellikle bu kadar kolay değil (HTTP Basic Authentication yöntemi hariç).
Hangi yöntem kullanılırsa kullanılsın HTTPS üzerinden kullanılması önemli. RESTApi tasarımında güvenlik için ilk söylenecek şey HTTPS kullanmak olsa gerek.
En çok kullanılan 4 tanesini inceleyelim bakalım;
HTTP Authentication
Basic Authentication
HTTP protokolünün en eski ve en temel yöntemi. Mevcut yöntemler arasında en kolay ama belki de en güvensiz olanı. İsteğin başlık bölümünde (Request Header) Base64 ile kodlanmış kullanıcı adı ve şifreyi göndermeye dayanıyor. Base64 bir şifreleme yöntemi olmadığı için açık olarak gönderildiğini kabul edebiliriz.
Authorization: Basic ZXZyZW46YmFs
Bearer
Bearer, İngilizcede Hamili/Taşıyıcısı gibi bir anlama geliyor. Bir nevi bu kodu taşıyan kişi hamili yakınımdır, içeriye alabilirsin demek. 🙂 İsteğin gönderim şekli olarak Basic Authentication’la benzer bir yapıya sahip olan Bearer yönteminde fark kullanıcı adı şifre yerine bir ‘token’ gönderiliyor olması.
Authorization: Bearer <token>
Bearer yöntemi ve yanında token oluşturma/doğrulama için JWT kullanıldığında hızlı ve pratik bir çözüm elde edilmiş oluyor. Ben bu ikilinin ileri seviye güvenlik gerektirmeyen çoğu uygulama için yeterli olduğunu düşünüyorum. Fakat JWT kullanacaksanız daha önce yazmış olduğum “JWT güvenli derken güvenlik açığı oluşturmayın” başlıklı yazımı okumanızı tavsiye ederim.
API ANAHTARLARI
Bu yöntem son kullanıcı uygulamalarından ziyade, tek seferlik (veya gerektiğinde) girilerek kullanılabilecek sistemler için kullanışlıdır. İsteğin sunucuya gönderilmesi Bearer yöntemine benzerdir. Fark API anahtarının oluşturulması ve istemci tarafında kaydedilmesi sürecindedir. O kullanıcıya servisinizi kullanabileceği benzersiz bir API anahtarı oluşturur ve o anahtarı kendi sisteminde/istemcisinde/kodunda tanımlamasını istersiniz. Örneğin bu blog için çeşitli servislerin API anahtarlarını wordpress yönetim panelinde ilgili ayar alanlarına girerek blogumun o servisleri kullanabilmesini sağlıyorum.
Fakat son kullanıcıya hitap eden bir mobil uygulama ve onun API’sinde sunucudan token’in alınması, istemcide saklanması, istek başlığında Bearer yöntemi ile gönderilmesi gibi işlemleri bizim yönetmemiz gerekiyor
OAuth 2.0 ve OpenID Connect
OAuth 2.0 kimlik doğrulamasından çok erişim yetkilendirmesi sağlayan bir yöntem. Örneğin bir web sitesine facebook hesabını bağladığınızda, Facebook’un o siteye “isminiz ve profile resminize ulaşma yetkisi vermesini” onaylamış, yani “bu siteye şu bilgilere ulaşabilmesi için bir erişim token’i ver” demiş oluyorsunuz.
Sizin API’ınızın da başka sitelerle entegre çalışabilmesi gerekiyorsa bunu OAuth 2.0 uygulaması ile çözebilirsiniz. Amacınız sunucunuz ve istemci arasında kimlik doğrulaması yapmaksa bunu OAuth 2.0’ı temel alan OpenID Connect ile çözmelisiniz.
OpenID Connect, bir doğrulama sunucunsun istemciyi doğrulamasını sağlıyor. Uygulamanız ve istemci arasında yine bir ekstra sunucu var ama bu sefer bu sunucunun işi istemcinin kimlik doğrulamasını yaparak gerekli temel bilgileri sizin uygulamanızla paylaşmak gibi düşünebilirsiniz.
OpenID kimlik doğrulamasını için üçüncü parti bir OpenID Provider kullanılabilir veya OpenID Web sitesindeki çeşitli kütüphanelere kendi doğrulama çözümünüzü oluşturabilirsiniz.
Hangi yöntemi tercih etmeliyiz?
Bu yöntemler arasında tek bir doğru olmadığı gibi yanlış olan bir yöntem de yok. Kullanım ve güvenlik ihtiyaçlarına göre hangi yöntemi kullanacağınız da değişiklik gösterecektir. Dikkat ederseniz her yöntem için verdiğim örnek farklı ihtiyaçlara hizmet ediyor.
Sorularınız varsa veya fikir alışverişi yapmak isterseniz yorumlardan, Twitter , LinkedIn veya Instagram üzerinden ulaşabilirsiniz. Sevgiler…
Bundan sonraki bölümde hata yönetimi nasıl yapılmalı kısaca onu inceleyeceğiz.
Bu Yazıda Yapılan Değişiklikler
- 11.05.2022: Yazı özeti düzenlendi.