使用restTemplate发送带有身份验证标头的GET请求

spe*_*0ne 71 java spring spring-mvc resttemplate

我需要通过使用RestTemplate发送带有一些Authorization标头的GET请求来从我的服务器检索资源.

在浏览了文档之后,我注意到没有一个GET方法接受头作为参数,并且发送Headers(如accept和Authorization)的唯一方法是使用exchange方法.

由于这是一个非常基本的行动,我想知道我是否遗漏了一些东西,还有另一种更简单的方法吗?

Sot*_*lis 61

你没有遗漏任何东西.RestTemplate#exchange(..)是用于设置请求标头的适当方法.

这是一个示例(使用POST,但只需将其更改为GET并使用您想要的实体).

这是另一个例子.

请注意,使用GET,您的请求实体不必包含任何内容(除非您的API期望它,但这将违反HTTP规范).它可以是一个空字符串.


iwe*_*ein 44

您可以使用postForObjectHttpEntity.它看起来像这样:

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);
Run Code Online (Sandbox Code Playgroud)

在GET请求中,您通常不会发送正文(它是允许的,但它没有任何用途).在不对RestTemplate进行布线的情况下添加标头的方法是直接使用exchangeexecute方法.get shorthands不支持标头修改.

乍一看,这种不对称有点奇怪,也许这将在未来的Spring版本中修复.

  • 问题是关于 GET 请求的,但这个答案是关于 POST 的。这是误导性的。没有带有这样签名的“getForObject”。 (8认同)
  • `restTemplate.postForEntity(url,entity,String.class)`也可以正常工作。 (2认同)

Dav*_*ave 24

这是一个带有基本身份验证,标头和异常处理的超级简单示例......

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不知道为什么这最初被低估了.如果您是第一个投票的人,请随时在评论中解释. (2认同)
  • "基本"部分不应编码,是不是? (2认同)

ide*_*tor 9

所有这些答案似乎都是不完整的和/或kludges.看看RestTemplate接口,它确实看起来像是要ClientHttpRequestFactory注入它,然后requestFactory将用于创建请求,包括头,正文和请求参数的任何自定义.

你需要一个通用ClientHttpRequestFactory的注入单个共享RestTemplate,否则你需要通过一个新的模板实例new RestTemplate(myHttpRequestFactory).

不幸的是,创建这样的工厂看起来有点不重要,即使你只是想设置一个Authorization标头,考虑到可能的常见要求,这是非常令人沮丧的,但至少它允许使用方便,例如,您的Authorization标头可以从Spring-Security Authorization对象中包含的数据创建,然后您可以创建一个工厂,通过执行每个请求设置传出AuthorizationHeader SecurityContextHolder.getContext().getAuthorization(),然后填充标头,并进行适当的空检查.现在,使用该RestTemplate进行的所有出站休息调用都将具有正确的授权标头.

在没有更多地强调HttpClientFactory机制的情况下,为常见情况提供简单到重载的基类,例如向请求添加单个头,大多数好的便利方法RestTemplate最终都是浪费时间,因为它们很少被使用.

我希望看到像这样简单的东西

@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();
        }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

目前,可用的ClientHttpRequestFactory的界面比那更难交互.更好的是现有工厂实现的抽象包装器,使它们看起来像一个更简单的对象,如AbstractHeaderRewritingRequestFactory,目的是替换这一个功能.现在,它们非常通用,即使编写这些包装也是一项复杂的研究.

  • 尽管您的“答案”非常有趣,但其读起来更像是评论,而不是实际答案。 (2认同)

Ama*_*icA 8

现在,类似以下内容就足够了:

HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
restTemplate.exchange(RequestEntity.get(new URI(url)).headers(headers).build(), returnType);
Run Code Online (Sandbox Code Playgroud)