Android'da Java ile ağda güvenli çalışma
Kısa cevap: Basit istekler için HttpsURLConnection uygundur, ancak üretim ortamında doğru zaman aşımları, TLS pinning ve UI thread dışı istek yürütme ile OkHttp kullanın.
Hızlı gereksinimler ve ayarlar
- Android uygulamasının manifest dosyasında izinlere ihtiyacı vardır:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- Android 9 (API 28) itibarıyla varsayılan olarak düz HTTP yasaktır. Testler için cleartext trafiği yalnızca belirli bir alan adı için network_security_config aracılığıyla etkinleştirebilirsiniz, ancak üretimde HTTPS kullanın.
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">example.com</domain>
</domain-config>
</network-security-config>
ve manifest dosyasında android:networkSecurityConfig="@xml/network_security_config".
Üretim ortamında TLS doğrulamasını devre dışı bırakmayın. SSL'i görmezden gelmek (TrustAll) MITM zafiyetine yol açar ve Google Play tarafından reddedilmenize neden olur.
java.net (HttpURLConnection) ile çalışma: kompakt örnekler ve önemli detaylar
HttpURLConnection/HttpsURLConnection "kutudan çıkar çıkmaz" kullanılabilir. Temel kurallar: zaman aşımlarını ayarlayın, responseCode'u okuyun, akışları kapatın ve asla UI thread üzerinde çalıştırmayın.
Basit GET:
public String makeGetRequest(String urlString) throws IOException {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
try {
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setRequestProperty("Accept", "application/json");
int code = conn.getResponseCode();
InputStream is = (code >= 200 && code < 300) ? conn.getInputStream() : conn.getErrorStream();
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) sb.append(line);
if (code >= 200 && code < 300) return sb.toString();
throw new IOException("HTTP " + code + ": " + sb.toString());
}
} finally {
conn.disconnect();
}
}
JSON ile POST:
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type","application/json; charset=utf-8");
// OutputStream'a yazma ve yanıtı okuma benzer şekilde yapılır
Temel noktalar:
- Her zaman connect/read zaman aşımlarını ayarlayın (5–10 sn).
- InputStream/OutputStream'ı kapatın ve conn.disconnect() çağırın.
- responseCode'u kontrol edin ve errorStream'i işleyin.
- Anahtarları doğrudan kod içinde saklamayın.
Neden çoğunlukla OkHttp tercih edilir ve nasıl güvenli kullanılır
OkHttp kodu basitleştirir, önbellekleme, sıkıştırma, yeniden deneme ve WebSocket desteği sunar. Üretim için OkHttp + CertificatePinner ve arka planda istek yürütme önerilir.
Senkron istek örneği (OkHttp):
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.build();
Request request = new Request.Builder()
.url("https://api.example.com/data")
.addHeader("Authorization", "Bearer " + token)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful() && response.body() != null) {
String body = response.body().string();
// işleme
} else {
// hata işleme
}
}
Asenkron olarak enqueue(callback) kullanın veya çağrıyı ExecutorService/WorkManager içinde yürütün.
Sertifika pinning:
- CertificatePinner, bir alan adı için güvenilir sertifikaları kısıtlamanıza olanak tanır.
- Pinning'i normal TLS doğrulamasıyla birleştirin ve pinleri önceden güncelleyin.
Yeni projeler için OkHttp ile başlayın: daha az boilerplate kod, yerleşik önbellekleme, HTTP/2 ve WebSocket desteği.
En iyi uygulamalar ve güvenlik (kontrol listesi)
- HTTPS ve modern TLS (1.2+) kullanın.
- Zaman aşımları: connect 5–10sn, read 5–15sn.
- Hostname/sertifika doğrulamasını devre dışı bırakmayın.
- Gizli bilgileri güvenli yerlerde saklayın (NDK, sunucu, şifrelenmiş tercihler), kod içinde değil.
- Ağ işlemlerini UI dışında yürütün (ExecutorService, WorkManager, RxJava).
- Ağ hatalarını işleyin: backoff ile yeniden deneme, ağ ve sunucu hatalarını ayırt edin.
- Body/akışları kapatın ve disconnect() çağırın.
Sık yapılan hatalar
- Zaman aşımları yok → uygulama "donar".
- Hata durumunda yalnızca InputStream okuma → hata mesajları kaybolur (errorStream kullanın).
- API anahtarlarını string kaynaklarında veya kodda saklama.
- Sertifika doğrulamasını görmezden gelme veya TrustAll kullanma.
SSS
- AsyncTask'tan ExecutorService'e geçmek gerekir mi? — Evet. AsyncTask artık kullanılmıyor; ExecutorService, WorkManager veya RxJava kullanın.
- Kötü ağda nasıl test yapılır? — Gecikmeleri ve paket kaybını simüle etmek için emülatör/Network Link Conditioner veya proxy'li bir dizüstü bilgisayar kullanın.
- HttpURLConnection ve OkHttp birleştirilebilir mi? — Evet, ancak tek bir yığın seçmek daha iyidir; OkHttp çoğu görev için HTTP katmanı olarak kullanılabilir.
- Pinning sırasında sunucu sertifikası değişirse ne yapılmalı? — Pinleri önceden güncelleyin ve erişimi kaybetmemek için fallback (birkaç geçerli pin) sağlayın.
Bu uygulamalarla Android'da Java ile ağ istekleriniz daha güvenilir ve güvenli hale gelecektir. Yeni projeler için OkHttp ile başlamanızı ve sağlam hata işleme ile gizli bilgilerin sunucuda saklanmasını öneririz.