使用Retrofit进行基本身份验证

时间:2016-06-15 08:38:13

标签: retrofit basic-authentication

我正在尝试使用Retrofit为REST API构建客户端。 API使用基本身份验证,我无法使用Retrofit进行身份验证。

我使用下面的curl测试了API,它按预期工作

Properties => Build tab => Advanced button => Language Version 

以下是Retrofit客户端

curl  -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{some_json}' -u api_key: https://apitest.com/api/v1/customers

当我在UserService上调用updateUser时

public interface UserService {

String HOST = "https://apitest.com";

public static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
public static Retrofit.Builder builder =
        new Retrofit.Builder()
                .baseUrl(HOST)
                .addConverterFactory(GsonConverterFactory.create());
/*
 * CREATE/UPDATE User
 */
@POST("api/v1/customers")
Call<UserAPIResponse> userUpdate(@Body UserUpdateRequest userUpdateRequest);



static UserService newInstance(String userAPIKey) {
    String credentials = userAPIKey + ":";

    final String basic = "Basic "+ Base64.encodeBase64(credentials.getBytes());

    httpClient.addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Interceptor.Chain chain) throws IOException {
            Request original = chain.request();

            Request.Builder requestBuilder = original.newBuilder()
                    .header("Authorization", basic);
            requestBuilder.header("Accept", "application/json");
            requestBuilder.method(original.method(),original.body());


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

OkHttpClient client = httpClient.build();
Retrofit retrofit = builder.client(client).build();

return retrofit.create(BlueshiftUserService.class);
}

response.code为401(未授权/身份验证失败)

带-u的curl命令和相同的凭据按预期工作。

3 个答案:

答案 0 :(得分:6)

问题在于凭证编码。我没有把它作为字符串发送。

byte[] encodedAuth= Base64.encodeBase64(credentials.getBytes());
final String basic = "Basic " + new String(encodedAuth);

答案 1 :(得分:1)

在Gradle文件中使用这些库

compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.3.0'
compile 'com.cookpad.android.rxt4a:rxt4a:0.9.0'
compile 'io.reactivex:rxjava:1.0.12'

并将这些课程放在您的项目中

 public class ServiceGenerator { 
  private static final String TAG = erviceGenerator.class.getSimpleName();
  public static final int READ_TIMEOUT = 10000;
  public static final int CONNECT_TIMEOUT = 100000;   
     // No need to instantiate this class. 
  private ServiceGenerator(){}   
     public static <S> S createService(Class<S> serviceClass, String
   endpoint) {
       // Call basic auth generator method without user and pass
       return createService(serviceClass, endpoint, null, null);   }

     public static <S> S createService(Class<S> serviceClass, String
   endpoint, String username, String password) {
       OkHttpClient okHttpClient = new OkHttpClient();
       okHttpClient.setReadTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
       okHttpClient.setConnectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);

       // Set endpoint url and use OkHTTP as HTTP client
       RestAdapter.Builder builder = new RestAdapter.Builder()
           .setEndpoint(endpoint)
           .setConverter(new GsonConverter(new Gson()))
           .setClient(new OkClient(okHttpClient));

       if (username != null && password != null) {
         // Concatenate username and password with colon for authentication
         final String credentials = username + ":" + password;

         builder.setRequestInterceptor(new RequestInterceptor() {
           @Override
           public void intercept(RequestFacade request) {
             // Create Base64 encoded string
             String string = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
             request.addHeader("Authorization", string);
             request.addHeader("Accept", "application/json");
           }
         });
       }

       RestAdapter adapter = builder.build();

       return adapter.create(serviceClass);   } }

和这个界面

public class TodolyClient {

  private static final String TAG = TodolyClient.class.getSimpleName();

  public static final String ENDPOINT = "your base URL";

  public interface TodolyService {

    @GET("/wp-json/wc/v2/products")(your remaining url)
    Observable<Object> isAuthenticated();


  }
}

并在主要活动中调用以下方法

private void createProject() {
 final TodolyClient.TodolyService service =ServiceGenerator.createService(
                TodolyClient.TodolyService.class, TodolyClient.ENDPOINT, "your user name",
                "your password");

        Observable<Object> observable = service.isAuthenticated();
         AndroidCompositeSubscription compositeSubscription = new AndroidCompositeSubscription();
        observable
                .lift(new OperatorAddToCompositeSubscription<Object>(compositeSubscription))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Object>() {

                    @Override
                    public void onNext(Object project) {
                        android.util.Log.d(TAG, "onNext: "+project.toString());
                    }

                    @Override
                    public void onCompleted() {
                        android.util.Log.d(TAG, "onNext:commm " );
                    }

                    @Override
                    public void onError(Throwable e) {
                        android.util.Log.d(TAG, "onNext: eeeeeeeee"+e.getMessage());

                    }
                });
    }

答案 2 :(得分:0)

这是迄今为止我尝试过的最简单的“基本身份验证”方法。

使用以下代码生成auth标头(API /存储库类),您可以在此处添加任何编码字符集作为第三个参数。

 var basic = Credentials.basic("YOUR_USERNAME", "YOUR_PASSWORD")

将此作为标头传递到Web服务调用(API /存储库类)

 var retrofitCall = myWebservice.getNewsFeed(basic)

添加基本标头作为参数(Retrofit Web服务接口类)

 @GET("newsfeed/daily")
 fun getNewsFeed(@Header("Authorization") h1:String):Call<NewsFeedResponse>

对不起,我的代码在Kotlin中,但是可以轻松地翻译成Java。

参考:https://mobikul.com/basic-authentication-retrofit-android/