重用现有令牌,而不是在 spring boot + Retrofit app 中的每个请求中请求它
Reuse existing token rather than requesting it on every request in spring boot + Retrofit app
我有一个 spring 启动应用程序,它使用 Retrofit 向安全服务器发出请求。
我的终点:
public interface ServiceAPI {
@GET("/v1/isrcResource/{isrc}/summary")
Call<ResourceSummary> getResourceSummaryByIsrc(@Path("isrc") String isrc);
}
public interface TokenServiceAPI {
@FormUrlEncoded
@POST("/bbcb6b2f-8c7c-4e24-86e4-6c36fed00b78/oauth2/v2.0/token")
Call<Token> obtainToken(@Field("client_id") String clientId,
@Field("scope") String scope,
@Field("client_secret") String clientSecret,
@Field("grant_type") String grantType);
}
配置class:
@Bean
Retrofit tokenAPIFactory(@Value("${some.token.url}") String tokenUrl) {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(tokenUrl)
.addConverterFactory(JacksonConverterFactory.create());
return builder.build();
}
@Bean
Retrofit serviceAPIFactory(@Value("${some.service.url}") String serviceUrl, TokenServiceAPI tokenAPI) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new ServiceInterceptor(clientId, scope, clientSecret, grantType, apiKey, tokenAPI))
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(repertoireUrl)
.client(okHttpClient)
.addConverterFactory(JacksonConverterFactory.create());
return builder.build();
}
为每个请求添加授权header的拦截器
public class ServiceInterceptor implements Interceptor {
public ServiceInterceptor(String clientId,
String scope,
String clientSecret,
String grantType,
String apiKey,
TokenServiceAPI tokenAPI) {
this.clientId = clientId;
this.scope = scope;
this.clientSecret = clientSecret;
this.grantType = grantType;
this.apiKey = apiKey;
this.tokenAPI = tokenAPI;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader(AUTHORIZATION_HEADER, getToken())
.addHeader(API_KEY_HEADER, this.apiKey)
.build();
return chain.proceed(newRequest);
}
private String getToken() throws IOException {
retrofit2.Response<Token> tokenResponse = repertoireTokenAPI.obtainToken(clientId, scope, clientSecret, grantType).execute();
String accessToken = "Bearer " + tokenAPI.body().getAccessToken();
return accessToken;
}
}
这按预期工作,问题是为每个请求请求令牌而不是使用现有的有效请求。如何将令牌存储在某处并 re-use 它?我想知道 Retrofit 是否有 built-in 解决方案。
一个可能的缓存选项:
添加咖啡因
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
在返回令牌的方法上添加@Cacheable("your-token-cache-name")
,看起来像上面的getToken
在application.yml
中添加最大缓存大小和过期配置
例如500 个条目和 10 分钟以下配置
spring.cache.cache-names=your-token-cache-name
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
示例来自:https://www.javadevjournal.com/spring-boot/spring-boot-with-caffeine-cache/
我有一个 spring 启动应用程序,它使用 Retrofit 向安全服务器发出请求。
我的终点:
public interface ServiceAPI {
@GET("/v1/isrcResource/{isrc}/summary")
Call<ResourceSummary> getResourceSummaryByIsrc(@Path("isrc") String isrc);
}
public interface TokenServiceAPI {
@FormUrlEncoded
@POST("/bbcb6b2f-8c7c-4e24-86e4-6c36fed00b78/oauth2/v2.0/token")
Call<Token> obtainToken(@Field("client_id") String clientId,
@Field("scope") String scope,
@Field("client_secret") String clientSecret,
@Field("grant_type") String grantType);
}
配置class:
@Bean
Retrofit tokenAPIFactory(@Value("${some.token.url}") String tokenUrl) {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(tokenUrl)
.addConverterFactory(JacksonConverterFactory.create());
return builder.build();
}
@Bean
Retrofit serviceAPIFactory(@Value("${some.service.url}") String serviceUrl, TokenServiceAPI tokenAPI) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new ServiceInterceptor(clientId, scope, clientSecret, grantType, apiKey, tokenAPI))
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(repertoireUrl)
.client(okHttpClient)
.addConverterFactory(JacksonConverterFactory.create());
return builder.build();
}
为每个请求添加授权header的拦截器
public class ServiceInterceptor implements Interceptor {
public ServiceInterceptor(String clientId,
String scope,
String clientSecret,
String grantType,
String apiKey,
TokenServiceAPI tokenAPI) {
this.clientId = clientId;
this.scope = scope;
this.clientSecret = clientSecret;
this.grantType = grantType;
this.apiKey = apiKey;
this.tokenAPI = tokenAPI;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader(AUTHORIZATION_HEADER, getToken())
.addHeader(API_KEY_HEADER, this.apiKey)
.build();
return chain.proceed(newRequest);
}
private String getToken() throws IOException {
retrofit2.Response<Token> tokenResponse = repertoireTokenAPI.obtainToken(clientId, scope, clientSecret, grantType).execute();
String accessToken = "Bearer " + tokenAPI.body().getAccessToken();
return accessToken;
}
}
这按预期工作,问题是为每个请求请求令牌而不是使用现有的有效请求。如何将令牌存储在某处并 re-use 它?我想知道 Retrofit 是否有 built-in 解决方案。
一个可能的缓存选项:
添加咖啡因
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
在返回令牌的方法上添加@Cacheable("your-token-cache-name")
,看起来像上面的getToken
在application.yml
中添加最大缓存大小和过期配置
例如500 个条目和 10 分钟以下配置
spring.cache.cache-names=your-token-cache-name
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
示例来自:https://www.javadevjournal.com/spring-boot/spring-boot-with-caffeine-cache/