
Kullanıcıların online bir hizmete güvenli bir şekilde erişebilmesi için hizmette kimlik doğrulaması yapmaları, kimlik belgelerini sunmaları gerekir. Üçüncü taraf hizmetlerine erişen uygulamalar için güvenlik sorunu daha da karmaşıktır. Hizmete erişmek için kullanıcının kimliğinin doğrulanmasının yanı sıra uygulamanın, kullanıcı adına hareket etme yetkisine de sahip olması gerekir.
Üçüncü taraf hizmetlerde kimlik doğrulamayı ele almanın endüstri standardı yöntemi, OAuth2 protokolüdür. OAuth2, hem kullanıcı kimliğini hem de uygulamanın kullanıcı adına hareket etme yetkisini temsil eden, kimlik doğrulama jetonu adı verilen tek bir değer sağlar. Bu derste, OAuth2'yi destekleyen bir Google sunucusuna bağlanma gösterilmektedir. Örnek olarak Google hizmetleri kullanılsa da gösterilen teknikler, OAuth2 protokolünü doğru destekleyen tüm hizmetlerde çalışır.
OAuth2'nin kullanılması şunlar için yararlıdır:
- Hesabı kullanarak online bir hizmete erişmek için kullanıcıdan izin almak.
- Kullanıcı adına çevrimiçi bir hizmet için kimlik doğrulaması.
- Kimlik doğrulama hatalarını işleme.
Bilgi toplama
OAuth2'yi kullanmaya başlamak için, erişmeye çalıştığınız hizmetle ilgili API'ye özgü birkaç noktayı bilmeniz gerekir:
- Erişmek istediğiniz hizmetin URL'si.
- Uygulamanızın istediği belirli erişim türünü tanımlayan bir dize olan kimlik doğrulama kapsamı. Örneğin, Google Görevler'e salt okuma erişimi için kimlik doğrulama kapsamı
View your tasks
, Google Görevler'e okuma-yazma erişiminin kimlik doğrulama kapsamı iseManage your tasks
'dır. - Uygulamanızı hizmete tanımlayan dizeler olan istemci kimliği ve istemci gizli anahtarı. Bu dizeleri doğrudan hizmet sahibinden almanız gerekir. Google, istemci kimliklerini ve gizli anahtarları edinmek için kullanılan self servis bir sisteme sahiptir.
İnternet izni iste
Android 6.0 (API düzeyi 23) ve sonraki sürümleri hedefleyen uygulamalar için getAuthToken()
yönteminin kendisi herhangi bir izin gerektirmez. Ancak jeton üzerinde işlem gerçekleştirmek için aşağıdaki kod snippet'inde gösterildiği gibi manifest dosyanıza INTERNET
iznini eklemeniz gerekir:
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
Yetkilendirme jetonu isteme
Jetonu almak için AccountManager.getAuthToken()
numaralı telefonu arayın.
Dikkat: Bazı hesap işlemleri ağ iletişimi içerebileceği için AccountManager
yöntemlerinin çoğu eşzamansızdır. Bu, tüm kimlik doğrulama çalışmalarınızı tek bir işlevde yapmak yerine bunu bir geri çağırma dizisi olarak uygulamanız gerektiği anlamına gelir.
Aşağıdaki snippet'te, jetonu almak için bir dizi geri çağırmayla nasıl çalışılacağı gösterilmektedir:
Kotlin
val am: AccountManager = AccountManager.get(this) val options = Bundle() am.getAuthToken( myAccount_, // Account retrieved using getAccountsByType() "Manage your tasks", // Auth scope options, // Authenticator-specific options this, // Your activity OnTokenAcquired(), // Callback called when a token is successfully acquired Handler(OnError()) // Callback called if an error occurs )
Java
AccountManager am = AccountManager.get(this); Bundle options = new Bundle(); am.getAuthToken( myAccount_, // Account retrieved using getAccountsByType() "Manage your tasks", // Auth scope options, // Authenticator-specific options this, // Your activity new OnTokenAcquired(), // Callback called when a token is successfully acquired new Handler(new OnError())); // Callback called if an error occurs
Bu örnekte OnTokenAcquired
, AccountManagerCallback
yöntemini uygulayan bir sınıftır. AccountManager
, OnTokenAcquired
üzerinde Bundle
içeren bir AccountManagerFuture
ile run()
işlevini çağırıyor. Çağrı başarılı olduysa jeton Bundle
içindedir.
Jetonu Bundle
ürününden nasıl alabileceğiniz aşağıda açıklanmıştır:
Kotlin
private class OnTokenAcquired : AccountManagerCallback<Bundle> { override fun run(result: AccountManagerFuture<Bundle>) { // Get the result of the operation from the AccountManagerFuture. val bundle: Bundle = result.getResult() // The token is a named value in the bundle. The name of the value // is stored in the constant AccountManager.KEY_AUTHTOKEN. val token: String = bundle.getString(AccountManager.KEY_AUTHTOKEN) } }
Java
private class OnTokenAcquired implements AccountManagerCallback<Bundle> { @Override public void run(AccountManagerFuture<Bundle> result) { // Get the result of the operation from the AccountManagerFuture. Bundle bundle = result.getResult(); // The token is a named value in the bundle. The name of the value // is stored in the constant AccountManager.KEY_AUTHTOKEN. String token = bundle.getString(AccountManager.KEY_AUTHTOKEN); ... } }
Her şey yolunda giderse Bundle
, KEY_AUTHTOKEN
anahtarında geçerli bir jeton içerir ve işlem tamamlanmış olur.
İlk yetkilendirme jetonu isteğiniz, çeşitli nedenlerden dolayı başarısız olabilir:
- Cihaz veya ağdaki bir hata nedeniyle
AccountManager
aracının çalışmaması sağlandı. - Kullanıcı, uygulamanızın hesaba erişmesine izin vermemeye karar vermiştir.
- Saklanan hesap kimlik bilgileri, hesaba erişim elde etmek için yeterli değildir.
- Önbelleğe alınan yetkilendirme jetonunun süresi doldu.
Uygulamalar ilk iki durumu önemsiz olarak, genellikle yalnızca kullanıcıya bir hata mesajı göstererek ele alabilir. Ağ çalışmıyorsa veya kullanıcı erişim izni vermemeye karar verirse uygulamanızın bu konuda yapabileceği pek bir şey yoktur. Son iki durum biraz daha karmaşıktır çünkü düzgün çalışan uygulamaların bu hataları otomatik olarak ele alması beklenir.
Yetersiz kimlik bilgilerine sahip üçüncü hata durumu, AccountManagerCallback
ile aldığınız Bundle
(önceki örnekten OnTokenAcquired
) aracılığıyla iletilir. Bundle
, KEY_INTENT
anahtarında bir Intent
içeriyorsa kimlik doğrulayıcı, size geçerli bir jeton vermeden önce kullanıcıyla doğrudan etkileşimde bulunması gerektiğini bildiriyordur.
Kimlik doğrulayıcının bir Intent
döndürmesinin birçok nedeni olabilir. Kullanıcı bu hesaba ilk kez giriş yapıyor olabilir. Kullanıcının hesabının süresi dolmuş ve tekrar giriş yapması gerekiyor ya da saklanan kimlik bilgileri yanlış olabilir. Belki hesapta iki faktörlü kimlik doğrulama gerekiyor veya retina taraması yapmak için kamerayı etkinleştirmesi gerekiyor. Nedenin ne olduğu önemli değildir. Geçerli bir jeton istiyorsanız bunu almak için Intent
öğesini tetiklemeniz gerekir.
Kotlin
private inner class OnTokenAcquired : AccountManagerCallback<Bundle> { override fun run(result: AccountManagerFuture<Bundle>) { val launch: Intent? = result.getResult().get(AccountManager.KEY_INTENT) as? Intent if (launch != null) { startActivityForResult(launch, 0) } } }
Java
private class OnTokenAcquired implements AccountManagerCallback<Bundle> { @Override public void run(AccountManagerFuture<Bundle> result) { ... Intent launch = (Intent) result.getResult().get(AccountManager.KEY_INTENT); if (launch != null) { startActivityForResult(launch, 0); return; } } }
Örnekte startActivityForResult()
kullanıldığını unutmayın. Böylece, onActivityResult()
işlemini kendi etkinliğinize uygulayarak Intent
sonucunu yakalayabilirsiniz. Bu önemlidir: Kimlik doğrulayıcının Intent
yanıtından gelen sonucu yakalamazsanız kullanıcının kimlik doğrulamasını başarılı bir şekilde yapıp yapmadığını belirleyemezsiniz.
Sonuç RESULT_OK
ise kimlik doğrulayıcı, depolanan kimlik bilgilerini istediğiniz erişim düzeyi için yeterli olacak şekilde güncellemiştir. Bu durumda, yeni kimlik doğrulama jetonunu istemek için AccountManager.getAuthToken()
yöntemini tekrar çağırmanız gerekir.
Jetonun süresinin dolduğu son durum aslında bir AccountManager
hatası değildir. Bir jetonun süresinin dolup dolmadığını öğrenmenin tek yolu sunucuyla iletişime geçmektir. AccountManager
, tüm jetonlarının durumunu kontrol etmek için sürekli olarak çevrimiçi olmakta israf yaratır ve maliyetli olur. Bu hata yalnızca sizinki gibi bir uygulama, online bir hizmete erişmek için kimlik doğrulama jetonunu kullanmaya çalıştığında algılanabilir.
Online hizmete bağlanın
Aşağıdaki örnekte bir Google sunucusuna nasıl bağlanılacağı gösterilmektedir. Google, isteklerin kimliğini doğrulamak için endüstri standardı OAuth2 protokolünü kullandığından burada açıklanan teknikler geniş ölçüde uygulanabilir. Bununla birlikte, her sunucunun farklı olduğunu unutmayın. Durumunuzu hesaba katmak için bu talimatlarda küçük ayarlamalar yapmanız gerekebilir.
Google API'leri her istekle birlikte dört değer sağlamanızı gerektirir: API anahtarı, istemci kimliği, istemci gizli anahtarı ve kimlik doğrulama anahtarı. İlk üçü Google API Konsolu web sitesinden gelir. Sonuncusu, AccountManager.getAuthToken()
yöntemini çağırarak elde ettiğiniz dize değeridir. Bunları bir HTTP isteğinin parçası olarak Google Sunucusu'na iletirsiniz.
Kotlin
val url = URL("https://www.googleapis.com/tasks/v1/users/@me/lists?key=$your_api_key") val conn = url.openConnection() as HttpURLConnection conn.apply { addRequestProperty("client_id", your client id) addRequestProperty("client_secret", your client secret) setRequestProperty("Authorization", "OAuth $token") }
Java
URL url = new URL("https://www.googleapis.com/tasks/v1/users/@me/lists?key=" + your_api_key); URLConnection conn = (HttpURLConnection) url.openConnection(); conn.addRequestProperty("client_id", your client id); conn.addRequestProperty("client_secret", your client secret); conn.setRequestProperty("Authorization", "OAuth " + token);
İstek 401 HTTP hata kodu döndürürse jetonunuz reddedilmiştir. Son bölümde belirtildiği gibi, bunun en yaygın nedeni jetonun süresinin dolmasıdır. Çözüm basittir: AccountManager.invalidateAuthToken()
yöntemini çağırın ve jeton edinme işlemini bir kez daha tekrarlayın.
Süresi dolmuş jetonlar sık karşılaşılan bir durum olduğundan ve bunları düzeltmek çok kolay olduğundan çoğu uygulama, daha istemeden jetonun süresinin dolduğunu varsayar. Jetonu yenilemek, sunucunuz için ucuz bir işlemse AccountManager.getAuthToken()
hizmetine yapılan ilk çağrıdan önce AccountManager.invalidateAuthToken()
yöntemini çağırmayı tercih edebilir ve iki kez yetkilendirme jetonu isteme ihtiyacından kurtulabilirsiniz.