Android 如何在okhttp3身份验证程序中添加具有异步请求的使用刷新令牌的身份验证

Android 如何在okhttp3身份验证程序中添加具有异步请求的使用刷新令牌的身份验证,android,okhttp3,android-authenticator,ibm-appid,Android,Okhttp3,Android Authenticator,Ibm Appid,我有一个连接到Okhttp3客户端的验证器,当401响应到来时,它将被成功调用。在验证器中,我想用刷新令牌对用户进行身份验证。我正在使用IBM进行身份验证 private Authenticator getAuthenticator() { return new Authenticator() { @Override public Request authenticate(Route route, Response respons

我有一个连接到Okhttp3客户端的验证器,当401响应到来时,它将被成功调用。在验证器中,我想用刷新令牌对用户进行身份验证。我正在使用IBM进行身份验证

private Authenticator getAuthenticator() {
        return new Authenticator() {

            @Override
            public Request authenticate(Route route, Response response) throws IOException {
                // code to authenticate with refresh token 
                return null;
            }
        };
    }
我有以下代码要使用刷新令牌进行身份验证:

AppID.getInstance().signinWithRefreshToken(getApplicationContext(), refreshTokenString, new AuthorizationListener() {
    @Override
    public void onAuthorizationFailure(AuthorizationException exception) {
        //Exception occurred
    }

    @Override
    public void onAuthorizationCanceled() {
        //Authentication canceled by the user
    }

    @Override
    public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identityToken, RefreshToken refreshToken) {
        //User authenticated
    }
});

现在您可以看到,这是一个异步请求,我不能将这段代码放在验证器中,因为该方法将在调用onAuthorizationSuccess()之前返回。另外,AppId没有我可以使用的同步请求类型。您能告诉我如何在authenticator类中使用此代码吗。请帮我解决这个问题

我有两个解决方案可能会让您感兴趣:

  • 你自己给他打电话。这可能很难,但您也可以浏览以寻求帮助
  • 使用syncronous signinWithRefreshToken()调用Fork并修改,然后使用它。另外,请确保在原始回购协议中创建有关此更改的功能请求或请求,以便在下一版本中包含此更改。
    这样做的缺点是,您必须维护AppIDSDK的另一个分支,并在需要时超时合并新的更改

  • 我有一个解决方案。请尝试以下代码。

    将类设置为:TokenAuthenticator.java

    import android.content.Context;
    import android.support.annotation.Nullable;
    
    import com.dmlllc.insideride.common.Preferences;
    import com.dmlllc.insideride.model.AccessToken;
    import com.dmlllc.insideride.restModel.RestResponse;
    import com.dmlllc.insideride.restModel.requestModel.AccessTokenReq;
    
    import java.io.IOException;
    
    import okhttp3.Authenticator;
    import okhttp3.Request;
    import okhttp3.Response;
    import okhttp3.Route;
    
    public class TokenAuthenticator implements Authenticator {
    
        private Context context;
    
        public TokenAuthenticator(Context context) {
            this.context = context;
        }
    
        @Nullable
            @Override
            public Request authenticate(Route route, Response response) throws IOException {
                // Refresh your access_token using a synchronous api request
                AccessTokenReq accessTokenReq = new AccessTokenReq(Preferences.getPreferenceString(context, Preferences.USERNAME_FOR_TOKEN, ""),
                        Preferences.getPreferenceString(context, Preferences.PASSWORD_FOR_TOKEN, ""));
                try {
                    retrofit2.Response<RestResponse<AccessToken>> tokenResponse = Global.initRetrofit(context).getAccessToken(accessTokenReq).execute();
                    if (tokenResponse.body() != null) {
                        if (tokenResponse.body().getResStatus().equals("success")) {
                            SessionManager sessionManager = new SessionManager(context);
                            sessionManager.storeToken(tokenResponse.body().getResults().getYourAccessToken());
                            Preferences.setPreferenceString(context, Preferences.ACCESS_TOKEN, tokenResponse.body().getResults().getYourAccessToken());
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
    
                // Add new header to rejected request and retry it
                return response.request().newBuilder()
                        .header("Authorization", Preferences.getPreferenceString(context, Preferences.ACCESS_TOKEN, ""))
                        .build();
            }
        }
    
    希望它也能对您有所帮助。:)
    快乐编码

    应用程序ID没有同步API。Android SDK中的所有API都是异步的。但是,您可以通过发出带有AppID.getInstance().signinWithRefreshToken的请求并停止当前线程,以同步方式“包装”它们,直到回调中返回响应为止。您可以尝试使用Java的线程同步选项之一来实现这一点,例如:wait/notify、CountDownLatch、BlockingQueue、Future等。。。
    public static RestApi initRetrofit(Context context) {
            // For logging request & response (Optional)
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    
            TokenAuthenticator tokenAuthenticator = new TokenAuthenticator(context);
    
            OkHttpClient client = new OkHttpClient.Builder()
                    .authenticator(tokenAuthenticator)
                    .addInterceptor(loggingInterceptor)
                    .connectTimeout(1, TimeUnit.MINUTES)
                    .writeTimeout(1, TimeUnit.MINUTES)
                    .readTimeout(1, TimeUnit.MINUTES)
                    .build();
    
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(URL.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(client)
                    .build();
            return retrofit.create(RestApi.class);
        }