我需要使用RestTemplate通过发送带有授权标头的GET请求从我的服务器检索资源。
在查看文档后,我注意到没有任何GET方法接受标头作为参数,而发送标头(如接受和授权)的唯一方法是使用exchange方法。
由于这是一个非常基本的操作,我想知道是否有其他更简单的方法可以完成这个操作?
我需要使用RestTemplate通过发送带有授权标头的GET请求从我的服务器检索资源。
在查看文档后,我注意到没有任何GET方法接受标头作为参数,而发送标头(如接受和授权)的唯一方法是使用exchange方法。
由于这是一个非常基本的操作,我想知道是否有其他更简单的方法可以完成这个操作?
你可以使用 postForObject
和一个 HttpEntity
。代码如下:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer "+accessToken);
HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String result = restTemplate.postForObject(url, entity, String.class);
在一个GET请求中,通常不会发送请求体(尽管允许这样做,但没有任何意义)。如果想要添加标头而不必更改RestTemplate的连线方式,则可以直接使用exchange或execute方法。get快捷方式不支持标头修改。这是一个非常简单的示例,包含基本身份验证、头信息和异常处理...
private HttpHeaders createHttpHeaders(String user, String password)
{
String notEncoded = user + ":" + password;
String encodedAuth = "Basic " + Base64.getEncoder().encodeToString(notEncoded.getBytes());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Authorization", encodedAuth);
return headers;
}
private void doYourThing()
{
String theUrl = "http://blah.blah.com:8080/rest/api/blah";
RestTemplate restTemplate = new RestTemplate();
try {
HttpHeaders headers = createHttpHeaders("fred","1234");
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, String.class);
System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
}
catch (Exception eek) {
System.out.println("** Exception: "+ eek.getMessage());
}
}
现在,类似以下的内容就足够了:
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
restTemplate.exchange(RequestEntity.get(new URI(url)).headers(headers).build(), returnType);
@Configuration
public class MyConfig {
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate(new AbstractHeaderRewritingHttpClientFactory() {
@Override
public HttpHeaders modifyHeaders(HttpHeaders headers) {
headers.addHeader("Authorization", computeAuthString());
return headers;
}
public String computeAuthString() {
// do something better than this, but you get the idea
return SecurityContextHolder.getContext().getAuthorization().getCredential();
}
});
}
}
目前可用的ClientHttpRequestFactory接口比那更难与之交互。更好的方法是为现有工厂实现创建一个抽象包装器,使它们看起来像一个更简单的对象,例如AbstractHeaderRewritingRequestFactory,以替换仅需要更改的这个功能。目前,它们非常通用,因此即使编写这些包装器也是一个复杂的研究工作。
一个简单的解决方案是在RestTemplate的bean配置中配置所有调用所需的静态http头:
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate getRestTemplate(@Value("${did-service.bearer-token}") String bearerToken) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add((request, body, clientHttpRequestExecution) -> {
HttpHeaders headers = request.getHeaders();
if (!headers.containsKey("Authorization")) {
String token = bearerToken.toLowerCase().startsWith("bearer") ? bearerToken : "Bearer " + bearerToken;
request.getHeaders().add("Authorization", token);
}
return clientHttpRequestExecution.execute(request, body);
});
return restTemplate;
}
}
RestTemplate
类处于维护模式,不建议使用。尽可能使用WebClient
。RestTemplate
,以便不同组件可以重复使用。@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplateWithCustomApiKey(@Value("${api.key}") String apiKey) {
return new RestTemplateBuilder()
.requestCustomizers(clientHttpRequest -> clientHttpRequest.getHeaders().add("X-API-Key", apiKey))
.build();
}
@Bean
public RestTemplate restTemplateWithBearerTokenSupplier(JwtTokenProvider yourJwtTokenProvider) {
return new RestTemplateBuilder()
.requestCustomizers(clientHttpRequest -> clientHttpRequest.getHeaders().setBearerAuth(yourJwtTokenProvider.getAccessToken()))
.build();
}
@Bean
public RestTemplate restTemplateWithBasicAuth(@Value("${auth.user}") String user, @Value("${auth.pass}") String pass) {
return new RestTemplateBuilder()
.requestCustomizers(clientHttpRequest -> clientHttpRequest.getHeaders().setBasicAuth(user, pass))
.build();
}
}
restTemplate.postForEntity(url, entity, String.class)
也可以正常工作。 - AbdullgetForObject
。 - Zon