Kami menggunakan Retrofit di aplikasi Android kami, untuk berkomunikasi dengan server aman OAuth2. Semuanya berfungsi dengan baik, kami menggunakan RequestInterceptor untuk memasukkan token akses dengan setiap panggilan. Namun akan ada waktu, ketika token akses akan kedaluwarsa, dan token perlu di-refresh. Saat token kedaluwarsa, panggilan berikutnya akan kembali dengan kode HTTP Tidak Sah, sehingga mudah dipantau. Kita dapat memodifikasi setiap panggilan Retrofit dengan cara berikut: Pada kegagalan panggilan balik, periksa kode kesalahan, jika sama dengan Tidak Sah, segarkan token OAuth, lalu ulangi panggilan Retrofit. Namun, untuk ini, semua panggilan harus dimodifikasi, yang bukan solusi yang mudah dirawat, dan bagus. Apakah ada cara untuk melakukan ini tanpa mengubah semua panggilan Retrofit?
157
Jawaban:
Harap jangan gunakan
Interceptors
untuk berurusan dengan otentikasi.Saat ini, pendekatan terbaik untuk menangani otentikasi adalah dengan menggunakan
Authenticator
API baru , yang dirancang khusus untuk tujuan ini .OkHttp akan secara otomatis meminta para
Authenticator
kredensial ketika respon yang401 Not Authorised
mencoba kembali permintaan terakhir gagal dengan mereka.Lampirkan sebuah
Authenticator
ke caraOkHttpClient
yang sama Anda lakukan denganInterceptors
Gunakan klien ini saat membuat
Retrofit
RestAdapter
sumber
TokenAuthenticator
tergantung suatuservice
kelas. Theservice
kelas tergantung padaOkHttpClient
contoh. Untuk membuatOkHttpClient
saya perluTokenAuthenticator
. Bagaimana saya bisa memutus siklus ini? DuaOkHttpClient
s berbeda ? Mereka akan memiliki kolam koneksi yang berbeda ...Jika Anda menggunakan Retrofit > =
1.9.0
maka Anda dapat menggunakan Interceptor baru OkHttp , yang diperkenalkan di . Anda ingin menggunakan Pencegat Aplikasi , yang memungkinkan Anda untuk melakukannya .OkHttp 2.2.0
retry and make multiple calls
Interceptor Anda bisa terlihat seperti kodesemu ini:
Setelah Anda menentukan
Interceptor
, buatOkHttpClient
dan tambahkan interseptor sebagai Aplikasi Interceptor .Dan akhirnya, gunakan ini
OkHttpClient
saat membuatRestAdapter
.Peringatan: Seperti yang
Jesse Wilson
disebutkan (dari Square) di sini , ini adalah kekuatan yang berbahaya.Dengan itu, saya pasti berpikir ini adalah cara terbaik untuk menangani sesuatu seperti ini sekarang. Jika Anda memiliki pertanyaan, jangan ragu untuk bertanya dalam komentar.
sumber
Jika Anda memiliki, katakanlah, Retrofit
TokenService
yang Anda butuhkan di dalam AndaAuthenticator
tetapi Anda hanya ingin mengaturnya,OkHttpClient
Anda dapat menggunakannyaTokenServiceHolder
sebagai ketergantunganTokenAuthenticator
. Anda harus mempertahankan referensi untuk itu di tingkat aplikasi (tunggal). Ini mudah jika Anda menggunakan Dagger 2, jika tidak, buat saja bidang kelas di dalam Aplikasi Anda.Di
TokenAuthenticator.java
Di
TokenServiceHolder.java
:Pengaturan klien:
Jika Anda menggunakan Dagger 2 atau kerangka kerja injeksi ketergantungan serupa, ada beberapa contoh dalam jawaban untuk pertanyaan ini
sumber
TokenService
kelas dibuat?refreshToken()
dariservice.refreshToken().execute();
. Tidak dapat menemukan penerapannya di mana pun.Menggunakan
TokenAuthenticator
like @theblang answer adalah cara yang tepat untuk menanganirefresh_token
.Inilah alat saya (saya telah menggunakan Kotlin, Dagger, RX tetapi Anda dapat menggunakan ide ini untuk alat untuk kasus Anda)
TokenAuthenticator
Untuk mencegah siklus ketergantungan seperti komentar @Brais Gabin, saya membuat 2 antarmuka seperti
dan
AccessTokenWrapper
kelasAccessToken
kelasPencegat saya
Akhirnya, tambahkan
Interceptor
danAuthenticator
keOKHttpClient
layanan PotoAuthApi Anda saat membuatDemo
https://github.com/PhanVanLinh/AndroidMVPKotlin
Catatan
Aliran AuthenticatorgetImage()
mengembalikan 401 kode kesalahanauthenticate
metode di dalamTokenAuthenticator
akan dipecatnoneAuthAPI.refreshToken(...)
disebutnoneAuthAPI.refreshToken(...)
respons -> token baru akan ditambahkan ke headergetImage()
AUTO akan dipanggil dengan tajuk baru (HttpLogging
TIDAK AKAN mencatat panggilan ini) (intercept
di dalamAuthInterceptor
TIDAK AKAN DISEBUT )Jika
getImage()
masih gagal dengan kesalahan 401,authenticate
metode di dalamnyaTokenAuthenticator
akan menembakkan AGAIN dan AGAIN kemudian akan membuang kesalahan tentang metode panggilan berkali-kali (java.net.ProtocolException: Too many follow-up requests
). Anda dapat mencegahnya dengan menghitung tanggapan . Contoh, jika Andareturn null
masukauthenticate
setelah 3 kali coba lagi,getImage()
akan selesai danreturn response 401
Jika
getImage()
respons berhasil => kami akan menghasilkan hasilnya secara normal (seperti Anda menelepongetImage()
tanpa kesalahan)Semoga ini bisa membantu
sumber
Saya tahu ini utas lama, tapi kalau-kalau ada yang tersandung.
Saya menghadapi masalah yang sama, tetapi saya hanya ingin membuat satu OkHttpClient karena saya tidak berpikir saya perlu yang lain hanya untuk TokenAuthenticator itu sendiri, saya menggunakan Dagger2, jadi saya akhirnya menyediakan kelas layanan ketika Lazy disuntikkan ke dalam TokenAuthenticator, Anda dapat membaca lebih lanjut tentang injeksi Malas di belati 2 di sini , tapi itu seperti pada dasarnya mengatakan kepada Belati untuk TIDAK pergi dan membuat layanan yang dibutuhkan oleh TokenAuthenticator segera.
Anda dapat merujuk ke utas SO ini untuk kode sampel: Bagaimana cara mengatasi ketergantungan melingkar saat masih menggunakan Dagger2?
sumber
Anda dapat mencoba membuat kelas dasar untuk semua loader Anda di mana Anda dapat menangkap pengecualian tertentu dan kemudian bertindak sesuai kebutuhan. Buat semua loader Anda yang berbeda diperluas dari kelas dasar untuk menyebarkan perilaku.
sumber
Setelah penelitian panjang, saya mengkustomisasi klien Apache untuk menangani Refreshing AccessToken Untuk Retrofit Di mana Anda mengirim token akses sebagai parameter.
Memulai Adaptor Anda dengan Cookie Persistent Client
Cookie Persistent client yang mengelola cookie untuk semua permintaan dan memeriksa dengan setiap respons permintaan, jika itu akses tidak sah ERROR_CODE = 401, menyegarkan token akses dan memanggil kembali permintaan, jika tidak hanya memproses permintaan.
sumber
Menggunakan satu Interceptor (menyuntikkan token) dan satu Authenticator (operasi penyegaran) melakukan pekerjaan tetapi:
Saya punya masalah panggilan ganda juga: panggilan pertama selalu mengembalikan 401 : token tidak menyuntikkan pada panggilan pertama (pencegat) dan otentikasiator dipanggil: dua permintaan dibuat.
Cara mengatasinya hanya untuk mengaktifkan kembali permintaan ke build di Interceptor:
SEBELUM:
SETELAH:
DALAM SATU BLOK:
Semoga ini bisa membantu.
Sunting: Saya tidak menemukan cara untuk menghindari panggilan pertama untuk selalu mengembalikan 401 hanya menggunakan autentikator dan tidak ada pencegat
sumber
Untuk siapa saja yang ingin menyelesaikan panggilan bersamaan / paralel saat menyegarkan token. Ini solusinya
sumber