1. Pengantar
Sangat umum bagi aplikasi untuk bertukar data melalui internet. Karena aplikasi Anda mungkin berkomunikasi dengan server selain yang dipercaya, Anda perlu berhati-hati saat mengirim dan menerima informasi yang dapat bersifat sensitif dan pribadi.
Yang akan Anda buat
Dalam codelab ini, Anda akan membuat aplikasi yang menampilkan pesan. Setiap pesan akan berisi nama pengirim, pesan teks, dan URL ke "foto profil" mereka. Aplikasi ini akan menampilkan pesan tersebut dengan melakukan hal berikut:
|
Yang akan Anda pelajari
- Pentingnya komunikasi jaringan yang aman.
- Cara menggunakan library Volley untuk membuat permintaan jaringan.
- Cara menggunakan Konfigurasi Keamanan Jaringan untuk membantu komunikasi jaringan menjadi lebih aman.
- Cara mengubah beberapa opsi Konfigurasi Keamanan Jaringan lanjutan yang akan berguna selama pengembangan dan pengujian.
- Menjelajahi salah satu masalah keamanan jaringan yang paling umum dan melihat bagaimana Konfigurasi Keamanan Jaringan dapat membantu mencegahnya.
Yang akan Anda butuhkan
- Versi terbaru Android Studio
- Perangkat Android atau emulator yang menjalankan Android 7.0 (API level 24) atau yang lebih tinggi
- Node.js (atau akses ke server web yang dapat dikonfigurasi)
Jika Anda mengalami masalah (bug kode, kesalahan gramatikal, susunan kata yang tidak jelas, dll.) saat mengerjakan codelab ini, laporkan masalah tersebut melalui link Laporkan kesalahan di pojok kiri bawah codelab.
2. Mempersiapkan
Download Kode
Klik link berikut untuk mendownload semua kode untuk codelab ini:
Ekstrak file ZIP yang didownload. Tindakan ini akan mengekstrak folder root (android-network-secure-config
), yang berisi project Android Studio (SecureConfig/
) dan beberapa file data yang akan kita gunakan di tahap berikutnya (server/
).
Anda juga dapat melihat kode langsung dari GitHub: (Mulai dengan cabang master
.)
Kami juga telah menyiapkan cabang dengan kode akhir setelah masing-masing langkah. Jika Anda mengalami masalah, lihat cabang di GitHub, atau clone seluruh repositori: https://github.com/android/codelab-android-network-security-config/branches/all
3. Menjalankan aplikasi
Setelah mengklik ikon "muat", aplikasi ini akan mengakses server jarak jauh untuk memuat daftar pesan, nama, dan URL ke foto profilnya dari file JSON. Selanjutnya, pesan ditampilkan dalam daftar, dan aplikasi memuat gambar dari URL yang direferensikan.
Catatan: Aplikasi yang kita gunakan dalam codelab ini hanya untuk tujuan demo. Hal ini tidak mencakup penanganan error sebanyak yang Anda perlukan di lingkungan produksi.
Arsitektur Aplikasi
Aplikasi mengikuti pola MVP, memisahkan penyimpanan data dan akses jaringan (model) dari logika (presenter) dan tampilan (view).
Class MainContract
berisi kontrak yang menjelaskan antarmuka antara View dan Presenter:
MainContract.java
/*
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.networksecurity;
import com.example.networksecurity.model.Post;
/**
* Contract defining the interface between the View and Presenter.
*/
public interface MainContract {
interface View {
/**
* Sets the presenter for interaction from the View.
*
* @param presenter
*/
void setPresenter(Presenter presenter);
/**
* Displays or hides a loading indicator.
*
* @param isLoading If true, display a loading indicator, hide it otherwise.
*/
void setLoadingPosts(boolean isLoading);
/**
* Displays a list of posts on screen.
*
* @param posts The posts to display. If null or empty, the list should not be shown.
*/
void setPosts(Post[] posts);
/**
* Displays an error message on screen and optionally prints out the error to logcat.
*/
void showError(String title, String error);
/**
* Hides the error message.
*
* @see #showError(String, String)
*/
void hideError();
/**
* Displays an empty message and icon.
*
* @param showMessage If true, the message is show. If false, the message is hidden
*/
void showNoPostsMessage(boolean showMessage);
}
interface Presenter {
/**
* Call to start the application. Sets up initial state.
*/
void start();
/**
* Loads post for display.
*/
void loadPosts();
/**
* An error was encountered during the loading of profile images.
*/
void onLoadPostImageError(String error, Exception e);
}
}
Konfigurasi Aplikasi
Untuk tujuan demonstrasi, semua cache jaringan aplikasi ini telah dinonaktifkan. Idealnya, di lingkungan produksi, aplikasi akan menggunakan cache lokal untuk membatasi jumlah permintaan jaringan jarak jauh.
File gradle.properties
berisi URL tempat daftar pesan dimuat:
gradle.properties
postsUrl="http://storage.googleapis.com/network-security-conf-codelab.appspot.com/v1/posts.json"
Mem-build dan menjalankan aplikasi
- Mulai Android Studio dan buka direktori SecureConfig sebagai project Android.
- Klik "jalankan" untuk memulai aplikasi:
Screenshot dari aplikasi berikut menunjukkan tampilannya di perangkat:
4. Konfigurasi Keamanan Jaringan Dasar
Pada langkah ini, kita akan menyiapkan konfigurasi keamanan jaringan dasar dan mengamati error yang terjadi jika salah satu aturan dalam konfigurasi dilanggar.
Ringkasan
Konfigurasi Keamanan Jaringan memungkinkan aplikasi menyesuaikan setelan keamanan jaringan mereka melalui file konfigurasi deklaratif. Seluruh konfigurasi ada di dalam file XML ini, dan tidak perlu mengubah kode.
Hal ini memungkinkan untuk konfigurasi berikut:
- Memilih tidak menggunakan traffic cleartext: Menonaktifkan traffic cleartext.
- Trust anchor khusus: Menentukan Certificate Authority dan sumber yang dipercaya aplikasi.
- Penggantian khusus debug: Melakukan debug koneksi aman dengan aman tanpa memengaruhi build rilis.
- Penyematan sertifikat: Membatasi koneksi aman ke sertifikat tertentu.
File ini dapat diatur menurut domain, sehingga setelan keamanan jaringan dapat diterapkan ke semua URL atau hanya untuk domain tertentu.
Konfigurasi Keamanan Jaringan tersedia di Android 7.0 (API level 24) dan yang lebih tinggi.
Membuat file XML Konfigurasi Keamanan Jaringan
Buat file resource xml yang baru dengan nama network_security_config.xml
.
Di Android Project Panel di sisi kiri, klik kanan pada res
, lalu pilih New > Android resource file.
Tetapkan opsi berikut dan klik OK.
Nama file |
|
Jenis resource |
|
Elemen root |
|
Nama direktori |
|
Buka file xml/network_security_config.xml
(jika tidak otomatis terbuka).
Ganti kontennya dengan cuplikan berikut:
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" >
</base-config>
</network-security-config>
Konfigurasi ini berlaku untuk konfigurasi dasar, atau konfigurasi keamanan default aplikasi, serta menonaktifkan semua traffic cleartext.
Mengaktifkan Konfigurasi Keamanan Jaringan
Selanjutnya, tambahkan referensi ke konfigurasi aplikasi di file AndroidManifest.xml
.
Buka file AndroidManifest.xml
dan temukan elemen application
di dalamnya.
Pertama, hapus baris yang menetapkan properti android:usesCleartextTraffic="true"
.
Selanjutnya, tambahkan properti android:networkSecurityConfig
ke elemen application
di AndroidManifest, dengan merujuk pada resource file XML network_security_config
: @xml/network_security_config
Setelah menghapus dan menambahkan dua properti di atas, tag aplikasi pembuka seharusnya terlihat seperti berikut:
AndroidManifest.xml
<application
android:networkSecurityConfig="@xml/network_security_config"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:fullBackupContent="false"
tools:ignore="GoogleAppIndexingWarning">
...
Mengompilasi dan menjalankan aplikasi
Mengompilasi dan menjalankan aplikasi.
Anda akan melihat error - aplikasi ini mencoba memuat data melalui koneksi cleartext!
Dalam logcat, Anda akan melihat error ini:
java.io.IOException: Cleartext HTTP traffic to storage.googleapis.com not permitted
Aplikasi tidak memuat data karena masih dikonfigurasi untuk memuat daftar pesan dari koneksi HTTP yang tidak dienkripsi. URL yang dikonfigurasi di file gradle.properties
mengarah ke server HTTP yang tidak menggunakan TLS!
Mari kita ubah URL ini untuk menggunakan server lain dan memuat data melalui koneksi HTTPS yang aman.
Ubah file gradle.properties
seperti berikut:
gradle.properties
postsUrl="https://storage.googleapis.com/network-security-conf-codelab.appspot.com/v1/posts.json"
(Perhatikan protokol http s di URL.)
Anda mungkin perlu membuat ulang project agar perubahan ini dapat dipilih. Dari menu, pilih Build > Rebuild
.
Jalankan kembali aplikasi. Anda akan melihat pemuatan data sekarang karena permintaan jaringan menggunakan koneksi HTTPS:
5. Masalah Umum: Update sisi server
Konfigurasi Keamanan Jaringan dapat melindungi dari kerentanan saat aplikasi membuat permintaan melalui koneksi yang tidak aman.
Masalah umum lainnya yang Konfigurasi Keamanan Jaringan tangani adalah perubahan sisi server yang memengaruhi URL yang dimuat ke aplikasi Android. Misalnya, di aplikasi kita, bayangkan bahwa server mulai menampilkan URL HTTP yang tidak aman untuk foto profil, bukan URL HTTPS yang aman. Konfigurasi Keamanan Jaringan yang menerapkan koneksi HTTPS kemudian akan memunculkan pengecualian karena persyaratan ini tidak akan terpenuhi pada runtime.
Mengupdate backend aplikasi
Seperti yang mungkin telah Anda ketahui, aplikasi ini terlebih dahulu memuat daftar pesan, masing-masing merujuk URL ke foto profil.
Bayangkan ada perubahan pada data yang digunakan aplikasi, sehingga aplikasi meminta URL gambar yang berbeda. Mari kita simulasikan perubahan ini dengan memodifikasi URL data backend.
Ubah file gradle.properties
seperti berikut:
gradle.properties
postsUrl="https://storage.googleapis.com/network-security-conf-codelab.appspot.com/v2/posts.json"
(Perhatikan "v2" pada jalur!)
Anda mungkin perlu membuat ulang project agar perubahan ini dapat dipilih. Dari menu, pilih Build > Rebuild
.
Anda dapat mengakses backend "baru" dari browser untuk melihat file JSON yang dimodifikasi. Perhatikan bagaimana semua URL yang direferensikan menggunakan HTTP, bukan HTTPS.
Menjalankan aplikasi dan memeriksa error
Mengompilasi dan menjalankan aplikasi.
Aplikasi memuat pesan, namun gambar tidak dimuat. Periksa pesan error di aplikasi dan di logcat untuk melihat penyebabnya:
java.io.IOException: Cleartext HTTP traffic to storage.googleapis.com not permitted
Aplikasi masih menggunakan HTTPS untuk mengakses file JSON. Namun, link ke foto profil dalam file JSON menggunakan alamat HTTP, sehingga aplikasi mencoba memuat gambar melalui HTTP (tidak aman).
Melindungi data
Konfigurasi Keamanan Jaringan berhasil mencegah paparan data yang tidak disengaja. Dibandingkan mencoba mengakses data yang tidak aman, aplikasi akan memblokir upaya koneksi.
Bayangkan skenario seperti ini, saat perubahan pada backend tidak cukup diuji sebelum peluncuran. Menerapkan Konfigurasi Keamanan Jaringan ke aplikasi Android dapat menyebabkan terjadinya masalah yang serupa, bahkan setelah rilis aplikasi.
Mengubah backend untuk memperbaiki aplikasi
Ubah URL backend ke versi baru yang telah "diperbaiki". Contoh ini menyimulasikan perbaikan dengan mereferensikan foto profil menggunakan URL HTTPS yang benar.
Ubah URL backend di file gradle.properties
dan memuat ulang project:
gradle.properties
postsUrl="https://storage.googleapis.com/network-security-conf-codelab.appspot.com/v3/posts.json"
(Perhatikan v3 pada jalur!)
Jalankan kembali aplikasi. Ini berfungsi sebagaimana mestinya:
6. Konfigurasi khusus domain
Sejauh ini, kita telah menentukan konfigurasi keamanan jaringan di base-config
, yang menerapkan konfigurasi ke semua koneksi yang coba dibuat oleh aplikasi.
Anda dapat mengganti konfigurasi ini untuk tujuan tertentu dengan menetapkan elemen domain-config
. domain-config
mendeklarasikan opsi konfigurasi untuk kumpulan domain tertentu.
Mari update konfigurasi keamanan jaringan di aplikasi kita ke kode berikut:
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>
Konfigurasi ini menerapkan base-config
ke semua domain, kecuali untuk domain "localhost" dan subdomainnya, tempat diterapkannya konfigurasi yang berbeda.
Di sini, konfigurasi dasar mencegah traffic cleartext untuk semua domain. Tetapi, konfigurasi domain akan mengganti aturan tersebut, memungkinkan aplikasi mengakses localhost menggunakan cleartext.
Menguji menggunakan server HTTP lokal
Setelah aplikasi dapat mengakses localhost menggunakan cleartext, mari kita mulai server web lokal dan uji protokol akses ini.
Ada berbagai alat yang dapat digunakan untuk menghosting server web yang sangat dasar, termasuk Node.JS, Python, dan Perl. Dalam codelab ini, kita akan menggunakan modul Node.JS http-server
untuk menyalurkan data untuk aplikasi kita.
- Buka terminal dan instal
http-server
:
npm install http-server -g
- Buka direktori tempat Anda memeriksa kode, lalu buka direktori
server/
:
cd server/
- Mulai server web dan salurkan file yang berada di data/direktori:
http-server ./data -p 8080
- Buka browser web dan buka http://localhost:8080 untuk memastikan bahwa Anda dapat mengakses file dan melihat file "
posts.json
":
- Selanjutnya, teruskan port 8080 dari perangkat ke komputer lokal. Jalankan perintah berikut di jendela terminal yang lain:
adb reverse tcp:8080 tcp:8080
Aplikasi Anda kini dapat mengakses "localhost:8080" dari perangkat Android.
- Ubah URL yang digunakan untuk memuat data di aplikasi agar mengarah ke server baru di
localhost
. Ubah filegradle.properties
sebagai berikut: (Ingat, Anda mungkin perlu melakukan sinkronisasi project gradle setelah mengubah file ini.)
gradle.properties
postsUrl="http://localhost:8080/posts.json"
- Jalankan aplikasi dan verifikasi bahwa data dimuat dari komputer lokal. Anda dapat mencoba mengubah file
data/posts.json
dan memuat ulang aplikasi untuk mengonfirmasi bahwa konfigurasi baru berfungsi sebagaimana mestinya.
Selain - konfigurasi domain
Opsi konfigurasi yang berlaku untuk domain tertentu ditentukan di elemen domain-config
. Elemen ini dapat berisi beberapa entri domain
yang menentukan tempat aturan domain-config
harus diterapkan. Jika beberapa elemen domain-config
berisi entri domain
yang serupa, Konfigurasi Keamanan Jaringan akan memilih konfigurasi yang akan diterapkan ke URL yang diberikan berdasarkan jumlah karakter yang cocok. Konfigurasi yang berisi entri domain
yang cocok dengan karakter terbanyak (secara berurutan) dengan URL digunakan.
Konfigurasi domain dapat berlaku untuk beberapa domain dan mungkin juga disertai subdomain.
Contoh berikut menunjukkan Konfigurasi Keamanan Jaringan yang berisi beberapa domain. (Kami tidak mengubah aplikasi, ini hanya contoh!)
<network-security-config>
<domain-config>
<domain includeSubdomains="true">secure.example.com</domain>
<domain includeSubdomains="true">cdn.example.com</domain>
<trust-anchors>
<certificates src="@raw/trusted_roots"/>
</trust-anchors>
</domain-config>
</network-security-config>
Untuk detail selengkapnya, lihat definisi format file konfigurasi.
7. Penggantian debug
Saat mengembangkan dan menguji aplikasi yang didesain untuk membuat permintaan melalui HTTPS, Anda mungkin perlu menghubungkannya ke server web lokal atau lingkungan pengujian, seperti yang kita lakukan pada langkah sebelumnya.
Dibandingkan menambahkan penggunaan penuh untuk mengizinkan traffic cleartext untuk kasus penggunaan ini atau mengubah kode, opsi debug-override
di Konfigurasi Keamanan Jaringan memungkinkan Anda menetapkan opsi keamanan yang hanya berlaku saat aplikasi berjalan dalam mode debug; yaitu, saat android:debuggable
adalah true. Tindakan ini secara signifikan lebih aman dibandingkan menggunakan kode kondisional karena definisi khusus debug-nya yang eksplisit. Play Store juga mencegah aplikasi yang dapat di-debug dapat diupload, sehingga opsi ini menjadi lebih aman.
Mengaktifkan SSL di server web lokal
Sebelumnya, kita memulai server web lokal yang menyalurkan data melalui HTTP pada port 8080. Sekarang kita akan membuat sertifikat SSL yang ditandatangani sendiri dan menggunakannya untuk menyalurkan data melalui HTTPS:
- Buat sertifikat dengan mengubah ke direktori
server/
di jendela terminal, lalu dengan menjalankan perintah berikut: (Jika Anda masih menjalankan server http, Anda dapat menghentikannya sekarang dengan menekan[CTRL] + [C]
.)
# Run these commands from inside the server/ directory! # Create a certificate authority openssl genrsa -out root-ca.privkey.pem 2048 # Sign the certificate authority openssl req -x509 -new -nodes -days 100 -key root-ca.privkey.pem -out root-ca.cert.pem -subj "/C=US/O=Debug certificate/CN=localhost" -extensions v3_ca -config openssl_config.txt # create DER format crt for Android openssl x509 -outform der -in root-ca.cert.pem -out debug_certificate.crt
Tindakan ini akan menghasilkan otoritas sertifikat, menandatanganinya, dan menghasilkan sertifikat dalam format DER yang diperlukan Android.
- Jalankan server web dengan HTTPS, menggunakan sertifikat yang baru dibuat:
http-server ./data --ssl --cert root-ca.cert.pem --key root-ca.privkey.pem
Memperbarui URL backend
Mengubah aplikasi untuk mengakses server localhost melalui HTTPS.
Ubah file gradle.properties
:
gradle.properties
postsUrl="https://localhost:8080/posts.json"
Mengompilasi dan menjalankan aplikasi.
Aplikasi akan gagal dengan error karena sertifikat server tidak valid:
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Aplikasi tidak dapat mengakses server web karena server menggunakan sertifikat yang ditandatangani sendiri yang tidak dipercaya sebagai bagian dari sistem. Dibandingkan menonaktifkan HTTPS, kita akan menambahkan sertifikat yang ditandatangani sendiri ini untuk domain localhost pada langkah berikutnya.
Merujuk certificate authority khusus
Server web kini menyalurkan data menggunakan certificate authority (CA) yang ditandatangani sendiri yang tidak diterima oleh perangkat apa pun secara default. Jika mengakses server dari browser, Anda akan melihat peringatan keamanan: https://localhost:8080
Berikutnya, kita akan menggunakan opsi debug-overrides
di konfigurasi keamanan jaringan untuk mengizinkan certificate authority khusus ini hanya untuk domain localhost
:
- Ubah file
xml/network_security_config.xml
sehingga berisi hal berikut:
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<debug-overrides>
<trust-anchors>
<!-- Trust a debug certificate in addition to the system certificates -->
<certificates src="system" />
<certificates src="@raw/debug_certificate" />
</trust-anchors>
</debug-overrides>
</network-security-config>
Konfigurasi ini menonaktifkan traffic jaringan cleartext dan, untuk build debug*,* mengaktifkan certificate authority yang disediakan sistem, serta file sertifikat yang disimpan di direktori res/raw
.
Catatan: Konfigurasi debug secara implisit menambahkan <certificates src="system" />
, sehingga aplikasi akan tetap berfungsi tanpanya. Kami telah menambahkannya untuk menunjukkan cara menambahkannya di konfigurasi lanjutan.
- Selanjutnya, salin file "
debug_certificate.crt
" dari direktoriserver/
ke direktori resourceres/raw
aplikasi di Android Studio. Anda juga dapat menarik lalu melepas file ke lokasi yang benar di Android Studio.
Anda mungkin harus membuat direktori ini terlebih dahulu jika tidak ada.
Dari server/direktori, Anda dapat menjalankan perintah berikut untuk melakukannya. Jika tidak, gunakan file manager atau Android Studio untuk membuat folder dan menyalin file ke lokasi yang benar:
mkdir ../SecureConfig/app/src/main/res/raw/ cp debug_certificate.crt ../SecureConfig/app/src/main/res/raw/
Android Studio sekarang akan mencantumkan file debug_certificate.crt
di bawah app/res/raw
:
Menjalankan aplikasi
Mengompilasi dan menjalankan aplikasi. Aplikasi kini mengakses server web lokal kami melalui HTTPS menggunakan sertifikat debug yang ditandatangani sendiri.
Jika Anda mengalami error, periksa output logcat dengan cermat dan pastikan Anda telah memulai ulang http-server
dengan opsi command line baru. Periksa juga apakah file debug_certificate.crt
berada di lokasi yang benar (res/raw/debug_certificate.crt
).
8. Pelajari Lebih Lanjut
Konfigurasi Keamanan Jaringan mendukung banyak fitur lanjutan lainnya, termasuk yang berikut:
- Penyematan sertifikat
- Memercayai certificate authority yang diinstal pengguna
- Membatasi Kumpulan CA Tepercaya
Saat menggunakan fitur tersebut, periksa dokumentasi untuk detail tentang praktik terbaik serta batasannya.
Buat aplikasi Anda lebih aman!
Sebagai bagian dari codelab ini, Anda telah mempelajari cara menggunakan Konfigurasi Keamanan Jaringan untuk meningkatkan keamanan aplikasi Android. Pikirkan bagaimana aplikasi Anda dapat memanfaatkan fitur tersebut dan bagaimana Anda dapat memanfaatkan konfigurasi debug yang lebih stabil untuk pengujian dan pengembangan.