【问题标题】:GET Request Works in Postman but not with RestTemplate - SpringBootGET 请求在 Postman 中有效,但不适用于 RestTemplate - SpringBoot
【发布时间】:2019-12-08 15:15:48
【问题描述】:

当我尝试通过邮递员发送时,我的请求运行良好。 我试图使用遇到错误的代码来实现相同的功能。

我正在使用的代码 -

RestTemplate restTemplate = new RestTemplate();    
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("client_id", clientid);
map.add("client_secret",clientsecret);

HttpEntity<?> request = new HttpEntity<>(map, headers);
logger.info(request.toString());

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(access_token_url)
                    .queryParam("grant_type", "client_credentials");

logger.info("URI -" + builder.toUriString());

ResponseEntity<String> response = restTemplate.exchange(builder.build().encode().toUri(), 
   HttpMethod.GET, request, String.class);
logger.info("Response" + response.getBody());

我得到的错误是 -

org.springframework.web.client.HttpClientErrorException$未授权: 401 未授权

但在 POSTMAN 中同样适用,但细节相同。

我想指定的东西

  • 后端 API 不在我手中。
  • clientid、clientsecret、access_token_url 是从属性文件中获取的,并且是正确的,我已经交叉检查了它们。
  • 这是一个带有 x-www-form-urlencoded 数据的 GET 请求。我检查了很多次它不是 POST
  • 没有像 Basic Auth 这样的授权,因为它没有在 POSTMAN 本身中设置
  • 经过This ThisThis 没有任何帮助。

我主要担心的是我从未见过任何地方发送带有方法主体的 GET 请求,但它在 POSTMAN 中工作,如果它在那里工作,为什么不在代码中工作?我哪里出错了?

编辑 - 1 用This 标记为重复,但总体上它的错误代码不同。 OP 得到了500 Internal Server Error,因为他提供了错误的内容类型。

编辑 - 2 调试输出-

2019-07-31 14:53:05.208 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : HTTP GET ORIGINAL_URL?grant_type=client_credentials
2019-07-31 14:53:05.215 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Accept=[text/plain, application/json, application/*+json, */*]
2019-07-31 14:53:05.218 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Writing [{client_id=[CLIENTID], client_secret=[CLIENT_SECRET]}] as "application/x-www-form-urlencoded"
2019-07-31 14:53:06.976 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.client.RestTemplate              : Response 401 UNAUTHORIZED
2019-07-31 14:53:07.034 DEBUG 3576 --- [nio-8080-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Using 'text/html', given [text/html, application/xhtml+xml, image/webp, image/apng, application/signed-exchange;v=b3, application/xml;q=0.9, */*;q=0.8] and supported [text/plain, */*, text/plain, */*, application/json, application/*+json, application/json, application/*+json]
2019-07-31 14:53:07.035 DEBUG 3576 --- [nio-8080-exec-1] m.m.a.RequestResponseBodyMethodProcessor : Nothing to write: null body
2019-07-31 14:53:07.039 DEBUG 3576 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2019-07-31 14:53:07.108 DEBUG 3576 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet        : GET "/favicon.ico", parameters={}
2019-07-31 14:53:07.119 DEBUG 3576 --- [io-8080-exec-10] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []]
2019-07-31 14:53:07.181 DEBUG 3576 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet        : Completed 200 OK

【问题讨论】:

  • 您是否记录了 spring 请求以查看它是否与您的邮递员请求相匹配?有一些有用的类,如stackoverflow.com/questions/7952154/…
  • 你能根据你的要求显示邮递员卷曲吗?
  • 您告诉我们一种方式行之有效,另一种方式行不通。您发布了无效的代码,但您没有发布有效的调用。我们是否应该猜测您的 API 是什么样的,以便我们修复您损坏的代码?
  • 这是正在工作的 curl curl -X GET \ 'URL-OF-CLIENT?grant_type=client_credentials' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'client_secret=SECRET&amp;client_id=ID'

标签: spring spring-boot resttemplate


【解决方案1】:

对于相同的用例,我们使用以下实现。

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
String token = new String(Base64.getEncoder().encode((clientId + ":" + clientSecret).getBytes()));
headers.add("Authorization", "Basic " + token);
HttpEntity<?> request = new HttpEntity<>(headers);
logger.info(request.toString());
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(access_token_url).queryParam("grant_type", "client_credentials");
logger.info("URI -" + builder.toUriString());
ResponseEntity<String> response = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.POST,request, String.class);
logger.info("Response" + response.getBody());

这可能会对你有所帮助。

【讨论】:

  • 这行得通!谢谢。你能解释一下我的错误是什么吗?
  • 1.您正在使用 GET,2. 您试图将客户端 ID 和客户端密码作为请求的一部分发送,而我们将它们作为授权标头的一部分发送
【解决方案2】:

我怀疑以下情况。您正在对您的网址进行双重编码,请更改:

restTemplate.exchange(builder.build().encode().toUri(), 
    HttpMethod.GET, request, String.class);

restTemplate.exchange(builder.build().toUri(), 
    HttpMethod.GET, request, String.class);

您可以通过启用 Spring Web 的调试来轻松匹配您的请求。

application.properties

logging.level.org.springframework.web: DEBUG

【讨论】:

  • 感谢调试提示。我测试了您的解决方案,仍然无法正常工作。它给了我和以前一样的结果
  • 请发布调试输出
  • 在 OP 中发布调试
猜你喜欢
  • 2020-07-07
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 2018-01-12
  • 2016-12-16
  • 2021-06-20
  • 2022-01-21
  • 2017-08-06
相关资源
最近更新 更多