Revifit2授权-访问令牌的全局拦截器

我想用 Retrofit2, 我想把 Token加到我的 Header中,像这样:

Authorization: Bearer Token but the code below doesn't work:

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

My server is asp.net webApi. Please help what should I do?

152358 次浏览

您有两个选择——可以将其作为参数添加到调用中——

@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();

如果您想添加承印人令牌作为标题,您可以执行这些类型的进程。

这是使用 来人令牌的一种方法

在你的界面里

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

After that you will call the Retrofit object in this way

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);

希望这对你有用。

基于@igreen 解决方案,由@Daniel Wilson 提出了不同类别和结构的 kotlin 版本

制作这样的改造实例

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
}
}


})

对于详细的 这个视频将有所帮助。

您需要在 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)
}
}
}

大声呼叫 JavaCodeMonk,并访问参考链接以获得更多详细信息。 Https://www.javacodemonk.com/retrofit-oauth2-authentication-okhttp-android-3b702350

这会将令牌添加到构建器中,并且在登录/注销的情况下可以随时更改令牌。

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


}

最好的方法是使用新的 AuthenticatorAPI。

class TokenAuthenticator : Authenticator {
override fun authenticate(route: Route?, response: Response): Request? {
if (response.request.header("Authorization") != null) {
return null
}
return response.request.newBuilder().header("Authorization", "Bearer " + token).build()
}
}
OkHttpClient.Builder().authenticator(TokenAuthenticator()).build()

Reference: https://square.github.io/okhttp/recipes/#handling-authentication-kt-java