Retrofit2:如何使授权令牌标头动态化?

Posted

技术标签:

【中文标题】Retrofit2:如何使授权令牌标头动态化?【英文标题】:Retrofit2: How to make authorization token header dynamic? 【发布时间】:2020-06-13 01:17:25 【问题描述】:

我正在创建一个允许用户使用基本身份验证登录的应用程序。

我有一个改造客户端,它使用 拦截器 来获取令牌。但是,它仅在您将电子邮件和密码指定为字符串而不是基于用户在登录表单中输入的电子邮件和密码时才有效。

在我的代码中,我将凭据设置为 email = "email@test.com" 和 password = "test" 并且代码有效并且用户能够登录。

但是我需要 AUTH 变量是动态的。我看到的所有示例和问题都有一个使用静态电子邮件和密码的解决方案。

我的改造客户是这样的

public class RetrofitClient 

    private static final String BASE_URL = "http://999.999.999:9999/api/";
    private static RetrofitClient mInstance;
    private Retrofit retrofit;

    private static final String AUTH =
            Credentials.basic("email@test.com", "test");


    private RetrofitClient()
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(
                        new Interceptor() 
                            @Override
                            public Response intercept(Chain chain) throws IOException 
                                Request original = chain.request();

                                Request.Builder requestBuilder = original.newBuilder()
                                        .addHeader("Authorization", AUTH)
                                        .method(original.method(), original.body());

                                Request request = requestBuilder.build();
                                return chain.proceed(request);
                            
                        
                ).build();

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();
    

    public static synchronized RetrofitClient getInstance() 
        if (mInstance == null) 
            mInstance = new RetrofitClient();
        
        return mInstance;

    



    public Api getApi()
        return retrofit.create(Api.class);
    

.

而我是这样称呼客户的

.

Call<LoginResponse> call = RetrofitClient
            .getInstance()
            .getApi()
            .userLogin(email, password);


    call.enqueue(new Callback<LoginResponse>() 
        @Override
        public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) 
            LoginResponse loginResponse = response.body();

            if(response.code() == 200)

                //save user
                //open profile

                Toast.makeText(LoginActivity.this, loginResponse.getToken(), Toast.LENGTH_SHORT).show();
             else 



                Toast.makeText(LoginActivity.this, "Error Logging in", Toast.LENGTH_SHORT).show();

            
        

        @Override
        public void onFailure(Call<LoginResponse> call, Throwable t) 

        
    );

【问题讨论】:

【参考方案1】:

实际上,您唯一需要做的就是将 AUTH 替换为其他数据源,这些数据源可以从您需要的代码的任何部分进行更改

解释。 intercept 方法在每个 api 请求上调用,因此您的凭据可以随时更改


例如

一些单例凭据提供程序

public class CredentialsProvider 

    //Some singleton stuff

    private Credentials credentials = Credentials.basic("email@test.com", "test"); //Some initial data

    public void setCredentials(Credentials credentials) 
        this.credentials = credentials
    

    public Credentials getCredentials() 
        return credentials;
    

代码中您要更改凭据的位置


    CredentialsProvider.getInstance().setCredentials(someNewCredentials);

改造

public class RetrofitClient 

   //Your code

   private CredentialsProvider credentialsProvider;
   // More code

   @Override
   public Response intercept(Chain chain) throws IOException 
       Request original = chain.request();
       Request.Builder requestBuilder = original.newBuilder()
           .addHeader("Authorization", credentialsProvider.getCredentials())
           .method(original.method(), original.body());

           Request request = requestBuilder.build();
           return chain.proceed(request);
       

【讨论】:

以上是关于Retrofit2:如何使授权令牌标头动态化?的主要内容,如果未能解决你的问题,请参考以下文章

如何在所有请求中传输动态auth值,而不是在SOAPUI中更改每个请求的标头中的值

Apollo GraphQL 的动态标头(中间件之外)

向标头添加授权并访问 [Authorize] 控制器

如何将标头动态传递给 angularjs 的 $resource

如何在传入的http请求标头中添加授权令牌[关闭]

如何在所有请求标头中传递授权令牌 - Spring Boot java