Настройка HTTPS в Android Studio: GET, авторизация и безопасность

Короткий ответ: используйте Network Security Config для ограничения cleartext и локального pinning, делайте HTTPS-запросы через Retrofit + OkHttp, добавляйте Bearer в Interceptor, а для продакшена — SSL pinning и отключённые debug‑хакі. Ниже — конкретные шаги и минимальные фрагменты кода, чтобы это сразу заработало.

Network Security Config и манифест

Создайте res/xml/network_security_config.xml, чтобы явно разрешать только HTTPS для вашего API и при необходимости подключать локальные сертификаты:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="false">
    <domain includeSubdomains="true">yourapi.com</domain>
    <trust-anchors>
      <certificates src="@raw/your_cert"/>
    </trust-anchors>
  </domain-config>
</network-security-config>

В AndroidManifest.xml:

<application
  android:networkSecurityConfig="@xml/network_security_config"
  android:usesCleartextTraffic="false"
  ...>

Для локальной разработки временно в debug-манифесте можно установить android:usesCleartextTraffic="true" и упрощённый hostnameVerifier, но никогда не оставляйте это в релизе.

GET-запросы с Retrofit и авторизация (Bearer Token)

Добавьте зависимости Retrofit/OkHttp (пример версии в вашем build.gradle). Настройте OkHttpClient с Interceptor для авторизации и логирования:

class AuthInterceptor(private var tokenProvider: () -> String?) : Interceptor {
  override fun intercept(chain: Interceptor.Chain): Response {
    val token = tokenProvider()
    val req = chain.request().newBuilder()
      .apply { token?.let { addHeader("Authorization", "Bearer $it") } }
      .addHeader("Content-Type", "application/json")
      .build()
    return chain.proceed(req)
  }
}

Инициализация Retrofit:

val client = OkHttpClient.Builder()
  .addInterceptor(AuthInterceptor { tokenStorage.currentToken })
  .addInterceptor(HttpLoggingInterceptor().apply { level = BODY }) // debug only
  .protocols(listOf(Protocol.HTTP_2, Protocol.HTTP_1_1))
  .build()

val retrofit = Retrofit.Builder()
  .baseUrl("https://yourapi.com/")
  .client(client)
  .addConverterFactory(GsonConverterFactory.create())
  .build()

Интерфейс API:

interface ApiService {
  @GET("users/{id}")
  suspend fun getUser(@Path("id") id: String): Response<User>
}

Используйте suspend-функции и вызывной scope (lifecycleScope или viewModelScope) — это проще и безопаснее, чем callbacks.

SSL pinning, отладка и продакшен‑практики

Для сильной защиты используйте CertificatePinner (OkHttp) или pin в network_security_config:

Пример CertificatePinner:

val pinner = CertificatePinner.Builder()
  .add("yourapi.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
  .build()

val client = OkHttpClient.Builder()
  .certificatePinner(pinner)
  .build()

Добавьте сертификат в res/raw/my_cert.crt, если используете network_security_config.

Отладка:

  • Для перехвата трафика (Charles, HTTP Toolkit) установите CA в эмулятор/устройство через Settings → Security → Install from storage (только для тестов).
  • Логи: фильтруйте Logcat по тегу OkHttp и включайте HttpLoggingInterceptor только в debug.

Продакшен:

  • Никогда не используйте hostnameVerifier { _, _ -> true }.
  • Ротация ключей: планируйте обновление pin каждые 6 месяцев (дублированные pin для перехода).
  • Сервер должен отдавать HSTS и поддерживать современных TLS‑cipherы.

Android 16 требует Certificate Transparency — подготовьтесь добавить ct-verifier в стек HTTPS уже сейчас.

Частые ошибки

  • SSLHandshakeException: неверный cert, отсутствует intermediate, или клиент не доверяет CA.
  • NetworkSecurityConfig игнорируется: проверьте корректность пути и android:networkSecurityConfig в манифесте.
  • Bearer не передаётся: Interceptor не добавлен или tokenProvider возвращает null.
  • Проблемы с эмулятором и CA: реальное устройство ведёт себя иначе — тестируйте на нём.

FAQ

  • Нужно ли HTTPS для публикации в Play Store? Да — Android 9+ по умолчанию блокирует cleartext и Google требует защищённого трафика.
  • Как временно разрешить HTTP для тестов? В debug‑варианте манифеста: android:usesCleartextTraffic="true" или настройка domain-config с cleartextTrafficPermitted="true" только для dev-домена.
  • Что выбрать: pinning в network_security_config или CertificatePinner? Network config проще для статичных cert в ресурсах; CertificatePinner удобнее для гибкого управления в коде и динамических обновлений.

Если нужно — могу прислать готовый модуль Application + Retrofit + примеры хранения токена для быстрого старта.