TokenAuthenticator
Like @theblang yanıtı kullanmak işlemek için doğru bir yoldur refresh_token
.
İşte benim alet (Kotlin, Dagger, RX kullanıyorum ama bu fikri davanıza uygulamak için kullanabilirsiniz)
TokenAuthenticator
class TokenAuthenticator @Inject constructor(private val noneAuthAPI: PotoNoneAuthApi, private val accessTokenWrapper: AccessTokenWrapper) : Authenticator {
override fun authenticate(route: Route, response: Response): Request? {
val newAccessToken = noneAuthAPI.refreshToken(accessTokenWrapper.getAccessToken()!!.refreshToken).blockingGet()
accessTokenWrapper.saveAccessToken(newAccessToken) // save new access_token for next called
return response.request().newBuilder()
.header("Authorization", newAccessToken.token) // just only need to override "Authorization" header, don't need to override all header since this new request is create base on old request
.build()
}
}
Öneleyen için bağımlılık döngüsü @Brais Gabin açıklama gibi, ben oluşturmak 2 arayüzü gibi
interface PotoNoneAuthApi { // NONE authentication API
@POST("/login")
fun login(@Body request: LoginRequest): Single<AccessToken>
@POST("refresh_token")
@FormUrlEncoded
fun refreshToken(@Field("refresh_token") refreshToken: String): Single<AccessToken>
}
ve
interface PotoAuthApi { // Authentication API
@GET("api/images")
fun getImage(): Single<GetImageResponse>
}
AccessTokenWrapper
sınıf
class AccessTokenWrapper constructor(private val sharedPrefApi: SharedPrefApi) {
private var accessToken: AccessToken? = null
// get accessToken from cache or from SharePreference
fun getAccessToken(): AccessToken? {
if (accessToken == null) {
accessToken = sharedPrefApi.getObject(SharedPrefApi.ACCESS_TOKEN, AccessToken::class.java)
}
return accessToken
}
// save accessToken to SharePreference
fun saveAccessToken(accessToken: AccessToken) {
this.accessToken = accessToken
sharedPrefApi.putObject(SharedPrefApi.ACCESS_TOKEN, accessToken)
}
}
AccessToken
sınıf
data class AccessToken(
@Expose
var token: String,
@Expose
var refreshToken: String)
Önleme Sahibim
class AuthInterceptor @Inject constructor(private val accessTokenWrapper: AccessTokenWrapper): Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val authorisedRequestBuilder = originalRequest.newBuilder()
.addHeader("Authorization", accessTokenWrapper.getAccessToken()!!.token)
.header("Accept", "application/json")
return chain.proceed(authorisedRequestBuilder.build())
}
}
Son olarak, eklemek Interceptor
ve Authenticator
sizin için OKHttpClient
oluşturabilir servis PotoAuthApi
gösteri
https://github.com/PhanVanLinh/AndroidMVPKotlin
Not
Kimlik doğrulayıcı akışı
- Örnek API
getImage()
dönüşü 401 hata kodu
authenticate
yöntem içeride TokenAuthenticator
olacak ateş
- Senkronize
noneAuthAPI.refreshToken(...)
denilen
- Yanıttan sonra
noneAuthAPI.refreshToken(...)
-> yeni simge başlığa eklenecek
getImage()
irade OTO denilen (yeni bir başlıkla HttpLogging
giriş OLMAYACAKTIR (bu çağrıyı) intercept
içindeki AuthInterceptor
WILL DİYE DEĞİL )
Eğer getImage()
hala hata 401 ile başarısız oldu, authenticate
içeride yöntem TokenAuthenticator
irade TEKRAR ateş ve TEKRAR (o zaman çağrı yöntemi birçok zaman hakkında hata atmak olacaktır java.net.ProtocolException: Too many follow-up requests
). Cevabı sayarak önleyebilirsiniz . Örnek, eğer return null
içinde authenticate
3 kez yeniden deneme sonrasında, getImage()
olacak bitirmek vereturn response 401
Eğer getImage()
(aramak gibi tepki başarı => normalde sonucu sonuçlanacaktır getImage()
hiçbir hata ile)
Umarım yardımcı olur