TokenAuthenticator
@theblang과 같은 답변을 사용 하는 것이 올바른 방법입니다 refresh_token
.
여기 내 구현이 있습니다 (Kotlin, Dagger, RX를 사용했지만이 아이디어를 귀하의 경우에 구현하기 위해 사용할 수 있습니다)
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()
}
}
@Brais Gabin 주석과 같은 종속성주기 를 방지하기 위해 다음 과 같은 2 개의 인터페이스를 만듭니다.
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>
}
과
interface PotoAuthApi { // Authentication API
@GET("api/images")
fun getImage(): Single<GetImageResponse>
}
AccessTokenWrapper
수업
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
수업
data class AccessToken(
@Expose
var token: String,
@Expose
var refreshToken: String)
내 요격기
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())
}
}
마지막으로 서비스 PotoAuthApi를 만들 때 Interceptor
and Authenticator
에 추가 하십시오.OKHttpClient
데모
https://github.com/PhanVanLinh/AndroidMVPKotlin
노트
인증 자 흐름
- API
getImage()
리턴 401 오류 코드 예
authenticate
방법의 내부는 TokenAuthenticator
것이다 발사
noneAuthAPI.refreshToken(...)
호출 된 동기화
noneAuthAPI.refreshToken(...)
응답 후 -> 새 토큰이 헤더에 추가됩니다.
getImage()
의지 AUTO라는 (새 헤더로 HttpLogging
로그인하지 않을 것이다 (이 호출)를 intercept
내부에 AuthInterceptor
의지가 호출되지 않습니다 )
getImage()
오류 401로 여전히 실패 하면 authenticate
내부 메소드 TokenAuthenticator
가 AGAIN 및 AGAIN 을 발생시키고 호출 메소드에 대한 오류를 여러 번 발생시킵니다 ( java.net.ProtocolException: Too many follow-up requests
). 카운트 응답으로 방지 할 수 있습니다 . 예를 들어, 만약 당신이 return null
에서 authenticate
3 번 시도 후 getImage()
것이다 완료 및return response 401
경우 getImage()
(당신이 전화 같은 응답 성공하기 => 우리는 일반적으로 결과를 발생합니다 getImage()
오류없이)
도움이되기를 바랍니다.