87

我正在使用 OAuth,每次发出请求时都需要将 OAuth 令牌放在我的标头中。我看到了@Header注释,但是有没有办法让它参数化,以便我可以在运行时传入?

这是概念

@Header({Authorization:'OAuth {var}', api_version={var} })

你可以在运行时传递它们吗?

@GET("/users")
void getUsers(
    @Header("Authorization") String auth, 
    @Header("X-Api-Version") String version, 
    Callback<User> callback
)
4

4 回答 4

100

除了使用 @Header 参数,我宁愿使用 RequestInterceptor 来更新你的所有请求而不改变你的界面。使用类似的东西:

RestAdapter.Builder builder = new RestAdapter.Builder()
    .setRequestInterceptor(new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {
            request.addHeader("Accept", "application/json;versions=1");
            if (isUserLoggedIn()) {
                request.addHeader("Authorization", getToken());
            }                    
        }
    });

p/s : 如果你使用的是 Retrofit2,你应该使用Interceptor而不是RequestInterceptor

由于RequestInterceptor在 Retrofit 2.0 中不再可用

于 2013-12-10T11:32:37.367 回答
56

是的,您可以在运行时传递它们。事实上,几乎与您输入的内容完全相同。这将在您的 API 接口类中,名为SecretApiInterface.java

public interface SecretApiInterface {

    @GET("/secret_things")
    SecretThing.List getSecretThings(@Header("Authorization") String token)

}

然后,您将请求中的参数传递给此接口,类似于以下内容:(此文件例如为SecretThingRequest.java

public class SecretThingRequest extends RetrofitSpiceRequest<SecretThing.List, SecretApiInteface>{

    private String token;

    public SecretThingRequest(String token) {
        super(SecretThing.List.class, SecretApiInterface.class);
        this.token = token;
    }

    @Override
    public SecretThing.List loadDataFromNetwork() {
        SecretApiInterface service = getService();
        return service.getSecretThings(Somehow.Magically.getToken());
    }
}

返回令牌的方法调用在哪里Somehow.Magically.getToken(),取决于您在哪里以及如何定义它。

您当然可以在接口实现中拥有多个@Header("Blah") String blah注释,就像您的情况一样!

我也发现它令人困惑,文档清楚地说它替换了标题,但它没有
它实际上是像@Headers("hardcoded_string_of_liited_use")注释一样添加的

希望这可以帮助 ;)

于 2013-09-12T01:29:13.160 回答
37

接受的答案是针对旧版本的 Retrofit。对于未来的观众,使用Retrofit2.0 执行此操作的方法是使用自定义 OkHttp 客户端:

OkHttpClient httpClient = new OkHttpClient.Builder()
  .addInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
      Builder ongoing = chain.request().newBuilder();
      ongoing.addHeader("Accept", "application/json;versions=1");
      if (isUserLoggedIn()) {
        ongoing.addHeader("Authorization", getToken());
      }
      return chain.proceed(ongoing.build());
    }
  })
  .build();

Retrofit retrofit = new Retrofit.Builder()
  // ... extra config
  .client(httpClient)
  .build();

希望它可以帮助某人。:)

于 2016-04-21T14:59:35.063 回答
8

改造 2.3.0

OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
    okHttpClientBuilder
            .addInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    Request.Builder newRequest = request.newBuilder().header("Authorization", accessToken);
                    return chain.proceed(newRequest.build());
                }
            });

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

我正在使用它连接到 GitHub。

于 2018-08-10T20:20:53.490 回答