如何在Retrofit中携带Basic Auth及指定Header发送POST请求?
问题描述
我希望在代码中发送携带Basic Auth的POST请求,Postman中已经配置了对应的Basic Auth认证(用户名EBA,令牌34242353453456563DSFS)。
我的ApiInterface类代码如下:
@FormUrlEncoded @POST("GetBarcodeDetail") Call<PreliminaryGoodsAcceptResponse> PRELIMINARY_GOODS_ACCEPT_RESPONSE_CALL( @Field("ProcName") String procName, @Field("Barcode") String barcode, @Field("LangCode") String langCode );
我的ApiClient类代码如下:
public class ApiClient { public static final String BASE_URL = "http://192.**********"; private static Retrofit retrofit = null; private static OkHttpClient sClient; public static Retrofit getClient() { if(sClient == null) { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); sClient = new OkHttpClient.Builder() .addInterceptor(new HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT)) .addInterceptor(interceptor) .build(); } if (retrofit==null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(sClient) .build(); } return retrofit; } }
请问如何通过添加Header(Username: EBA,Token: 34242353453456563DSFS)来发送该POST请求?
解决方案
针对你的需求,有两种常用的方式来添加Basic Auth认证头,我分别给你说明:
方式一:在单个接口方法中添加Header
如果你只需要给这一个接口添加认证,可以直接在ApiInterface的方法上添加注解,分两种场景:
固定认证信息(适合令牌不变的场景)
直接用@Headers注解添加固定的认证头,这里的认证值是EBA:34242353453456563DSFS经过Base64编码后的结果:
@FormUrlEncoded @POST("GetBarcodeDetail") @Headers({ "Authorization: Basic RUJBOjM0MjQyMzUzNDUzNDU2NTYzRkNGUw==" }) Call<PreliminaryGoodsAcceptResponse> PRELIMINARY_GOODS_ACCEPT_RESPONSE_CALL( @Field("ProcName") String procName, @Field("Barcode") String barcode, @Field("LangCode") String langCode );
动态传递认证信息(适合令牌可能变化的场景)
用@Header注解动态接收认证头参数,调用时再构造传入:
@FormUrlEncoded @POST("GetBarcodeDetail") Call<PreliminaryGoodsAcceptResponse> PRELIMINARY_GOODS_ACCEPT_RESPONSE_CALL( @Header("Authorization") String authHeader, @Field("ProcName") String procName, @Field("Barcode") String barcode, @Field("LangCode") String langCode );
调用示例:
// 构造认证头 String credentials = "EBA:34242353453456563DSFS"; String authHeader = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); // 发起请求 apiInterface.PRELIMINARY_GOODS_ACCEPT_RESPONSE_CALL(authHeader, procName, barcode, langCode);
方式二:全局添加认证拦截器(推荐)
如果你的多个接口都需要Basic Auth认证,更推荐在OkHttpClient中添加拦截器,自动给所有请求加上认证头,不用每个接口单独处理:
修改你的ApiClient类,添加认证拦截器:
public class ApiClient { public static final String BASE_URL = "http://192.**********"; private static Retrofit retrofit = null; private static OkHttpClient sClient; public static Retrofit getClient() { if(sClient == null) { // 构造Basic Auth认证头 String credentials = "EBA:34242353453456563DSFS"; final String authHeader = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); sClient = new OkHttpClient.Builder() .addInterceptor(new HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT)) .addInterceptor(interceptor) // 添加全局认证拦截器 .addInterceptor(chain -> { Request originalRequest = chain.request(); Request authenticatedRequest = originalRequest.newBuilder() .header("Authorization", authHeader) .build(); return chain.proceed(authenticatedRequest); }) .build(); } if (retrofit==null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(sClient) .build(); } return retrofit; } }
修改后,所有通过这个ApiClient创建的接口请求都会自动带上Basic Auth认证头,无需额外处理。如果你的令牌是动态获取的(比如登录后返回),可以把authHeader改成从SharedPreferences等存储中动态读取的方式。
内容的提问来源于stack exchange,提问作者cartoonworld




