Retrofit2 Authorization - глобальний перехоплювач для маркера доступу


78

Я намагаюся використовувати Retrofit2, я хочу додати Tokenдо мого HeaderПодобається так:

Authorization: Bearer Token але codeнижче не працює:

public interface APIService {
    @Headers({"Authorization", "Bearer "+ token})
    @GET("api/Profiles/GetProfile?id={id}")
    Call<UserProfile> getUser(@Path("id") String id);
}

Мій сервер asp.net webApi. Будь ласка, допоможіть, що мені робити?


Цей спосіб додавання заголовка працює лише тоді, коли 'маркер' є константою часу компіляції. Правила анотації Java тощо. Документація дає вам ще один спосіб включити заголовок: square.github.io/retrofit (зробіть це параметром методу)
zapl

Відповіді:


139

У вас є два варіанти - ви можете додати його як параметр до свого дзвінка -

@GET("api/Profiles/GetProfile?id={id}")
Call<UserProfile> getUser(@Path("id") String id, @Header("Authorization") String authHeader);

Це може трохи дратувати, тому що вам доведеться переходити під час "Bearer" + tokenкожного дзвінка. Це підходить, якщо у вас не так багато дзвінків, для яких потрібен маркер.

Якщо ви хочете додати заголовок до всіх запитів, ви можете використовувати перехоплювач okhttp -

OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
      @Override
      public Response intercept(Chain chain) throws IOException {
        Request newRequest  = chain.request().newBuilder()
            .addHeader("Authorization", "Bearer " + token)
            .build();
        return chain.proceed(newRequest);
      }
    }).build();

Retrofit retrofit = new Retrofit.Builder()
    .client(client)
    .baseUrl(/** your url **/)
    .addConverterFactory(GsonConverterFactory.create())
    .build();

1
Для мене я не усвідомлював, поки не реалізував його, але маркер відомий лише під час виконання - тому я вважаю, що це краще рішення: stackoverflow.com/questions/43051558/…
Даніель Вілсон,

Дякуємо, що працюємо над токеном на пред'явника, але як додати FieldMap з динамічним заголовком Я пробував із FieldMap, але він не працює. Прохання допомогти.
Dildarkhan Pathan

кулак: "Носій" + жетон. "Носій" + жетон. Потрібно порожній простір
Крістіанего

Проблема з другим. Метод полягає у використанні бібліотеки інжектора залежностей. Вам потрібно увійти в систему користувачеві, отримати маркер, перш ніж створювати екземпляри Okhttp для ur дзвінків
Declan Nnadozie

25

Якщо ви хочете додати маркер пред'явника як заголовок, ви можете виконати такі типи процесів.

Це один із способів роботи з жетоном на пред'явника

У вашому інтерфейсі

@Headers({ "Content-Type: application/json;charset=UTF-8"})
@GET("api/Profiles/GetProfile")
Call<UserProfile> getUser(@Query("id") String id, @Header("Authorization") String auth);

Після цього ви викличете об'єкт модернізації таким чином

Retrofit retrofit  = new Retrofit.Builder()
                    .baseUrl("your Base URL")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

APIService client = retrofit.create(APIService.class);
Call<UserProfile> calltargetResponse = client.getUser("0034", "Bearer "+token);
calltargetResponse.enqueue(new Callback<UserProfile>() {
       @Override
       public void onResponse(Call<UserProfile> call, retrofit2.Response<UserProfile> response) {
           UserProfile UserResponse = response.body();
           Toast.makeText(this, " "+response.body(), Toast.LENGTH_SHORT).show();
                }
        @Override
        public void onFailure(Call<UserProfile> call, Throwable t) {
            //Toast.makeText(this, "Failed ", Toast.LENGTH_SHORT).show();
        }
});

Інший спосіб - використовувати перехоплення, подібне до попередньої відповіді. Але, цього разу вам просто потрібно трохи змінити інтерфейс.

@Headers({ "Content-Type: application/json;charset=UTF-8"})
@GET("api/Profiles/GetProfile")
Call<UserProfile> getUser(@Query("id") String id); 

Сподіваюся, це буде працювати для вас.


10

Заснований на версії @iagreen kotlin з різними класами та структурою, запропонованою @Daniel Wilson

Зробіть зразок модернізації таким

object RetrofitClientInstance {
   private var retrofit: Retrofit? = null
   private val BASE_URL = "http://yoururl"


    val retrofitInstance: Retrofit?
        get() {
            if (retrofit == null) {
                var client = OkHttpClient.Builder()
                      .addInterceptor(ServiceInterceptor())
                      //.readTimeout(45,TimeUnit.SECONDS)
                      //.writeTimeout(45,TimeUnit.SECONDS)
                        .build()

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

            }
            return retrofit
      }

}

Додайте ServiceInterceptorклас, як показано нижче

class ServiceInterceptor : Interceptor{

  var token : String = "";

  fun Token(token: String ) {
     this.token = token;
  }

  override fun intercept(chain: Interceptor.Chain): Response {
    var request = chain.request()

    if(request.header("No-Authentication")==null){
        //val token = getTokenFromSharedPreference();
        //or use Token Function
        if(!token.isNullOrEmpty())
        {
            val finalToken =  "Bearer "+token
            request = request.newBuilder()
                    .addHeader("Authorization",finalToken)
                    .build()
        }

    }

    return chain.proceed(request)
  }

}

Інтерфейс входу та реалізація класу даних

interface Login {
  @POST("Login")
  @Headers("No-Authentication: true")
  fun login(@Body value: LoginModel): Call<LoginResponseModel>



  @POST("refreshToken")
  fun refreshToken(refreshToken: String): 
      Call<APIResponse<LoginResponseModel>>
}

data class LoginModel(val Email:String,val Password:String)
data class LoginResponseModel (val token:String,val 
         refreshToken:String)

називайте це в будь-якій подібній діяльності

val service = RetrofitClientInstance.retrofitInstance?.create(Login::class.java)
val refreshToken = "yourRefreshToken"
val call = service?.refreshToken(refreshToken)
        call?.enqueue(object: Callback<LoginResponseModel>{
            override fun onFailure(call: Call<LoginResponseModel>, t: Throwable) {
                print("throw Message"+t.message)
                Toast.makeText(applicationContext,"Error reading JSON",Toast.LENGTH_LONG).show()
            }

            override fun onResponse(call: Call<LoginResponseModel>, response: Response<LoginResponseModel>) {
                val body = response?.body()
                if(body!=null){
                    //do your work
                }
            }

        })

для деталей це відео буде корисним.


6

Це додає ваш токен до конструктора, і ви можете змінити його в будь-який час у разі входу / виходу.

object ApiService {
    var YOUR_TOKEN = ""

    private var retrofit: Retrofit = Retrofit.Builder()
        .baseUrl("YOUR_URL")
        .addConverterFactory(GsonConverterFactory.create())
        .client(OkHttpClient.Builder().addInterceptor { chain ->
            val request = chain.request().newBuilder().addHeader("Authorization", "Bearer ${YOUR_TOKEN}").build()
            chain.proceed(request)
        }.build())
        .build()

    var service: AppAPI = retrofit.create(AppAPI::class.java)
        private set

}

Чи означає це, що я повинен викликати Retrofit.Builder () щоразу, коли змінюється маркер? Я думав, що буду будувати Модернізацію один раз, потім вхід і після входу використовую маркер, поки термін його дії не закінчиться. Я ще не розумію. :)
Неймовірний

1

Вам потрібно буде додати перехоплювач в OkHttpClient.

Додайте клас із назвою OAuthInterceptor.

class OAuthInterceptor(private val tokenType: String, private val accessToken: String) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
        var request = chain.request()
        request = request.newBuilder().header("Authorization", "$tokenType $accessToken").build()

        return chain.proceed(request)
    }
}

Після цього, коли ви ініціалізуєте свій RetrofitApiServiceінтерфейс, вам це знадобиться.

interface RetrofitApiService {
    companion object {
        private const val BASE_URL = "https://api.coursera.org/api/businesses.v1/"
        fun create(accessToken: String): RetrofitApiService {
            val client = OkHttpClient.Builder()
                    .addInterceptor(OAuthInterceptor("Bearer", accessToken))
                    .build()

            val retrofit = Retrofit.Builder()
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl(BASE_URL)
                    .client(client)
                    .build()

            return retrofit.create(RetrofitApiService::class.java)
        }
    }
}

Зверніться до Java Code Monk та відвідайте посилання для отримання детальної інформації. https://www.javacodemonk.com/retrofit-oauth2-authentication-okhttp-android-3b702350

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.