【问题标题】:Curl Token request to Spring RestTemplate ConversionCurl Token 请求到 Spring RestTemplate 转换
【发布时间】:2020-03-28 21:29:19
【问题描述】:

我正在尝试将 curl 请求转换为 Spring 的 Resttemplate 发布请求,它给了我一个令牌,但我收到 403 - bad request

我的卷发请求

curl -d "grant_type=client_credentials&client_id=nu5yzeth9tektzf5egxuntp7&client_secret=uP2Xvr6SCKYgXgxxJsv2QkUG" 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -X POST https://cloudsso.example.com/as/token.oauth2

卷曲响应:

{"access_token":"HVURQ845OPJqs8UpOlef5m2ZCNwR","token_type":"Bearer","expires_in":3599}

现在,这是我实现上述 curl 发布请求的 Java 代码

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

MultiValueMap<String, String> bodyParamMap = new LinkedMultiValueMap<String, String>();
bodyParamMap.add("grant_type", "client_credentials");
bodyParamMap.add("client_id", "nu5yzeth9tektzf5egxuntp7");
bodyParamMap.add("client_secret", "uP2Xvr6SCKYgXgxxJsv2QkUG");

entity = new HttpEntity<>(reqBodyData, bodyParamMap);

restTemplate.postForEntity(url, entity, TokenDTO.class)

Resttemplate 调用响应:

2019-12-04 11:10:16,483[0;39m [39mDEBUG[0;39m [[34mrestartedMain[0;39m] [33morg.springframework.core.log.CompositeLog[0;39m: Accept=[application/json, application/*+json]
[30m2019-12-04 11:10:16,484[0;39m [39mDEBUG[0;39m [[34mrestartedMain[0;39m] [33morg.springframework.core.log.CompositeLog[0;39m: Writing [{"grant_type":["client_credentials"],"client_id":["nu5yzeth9tektzf5egxuntp7"],"client_secret":["uP2Xvr6SCKYgXgxxJsv2QkUG"]}] with org.springframework.http.converter.StringHttpMessageConverter
[30m2019-12-04 11:10:17,976[0;39m [39mDEBUG[0;39m [[34mrestartedMain[0;39m] [33morg.springframework.core.log.CompositeLog[0;39m: Response 400 BAD_REQUEST
[30m2019-12-04 11:10:17,981[0;39m [34mINFO [0;39m [[34mrestartedMain[0;39m] [33mcom.ibm.ciscoApiIntegration.service.impl.CiscoAPIServiceImpl[0;39m: e::: 400 Bad Request

如何使RestTemplate 中的上述 curl 请求正常工作?

注意:https://cloudsso.example.com/as/token.oauth2 对问题的修改很少。

【问题讨论】:

  • 我的建议是根本不这样做,并使用已经理解这一点的 OAuth2 客户端。有几种可用,其中一种用于与 RestTemplate 集成的 Spring。
  • 您需要在HttpHeaders 上正确设置内容类型,并且您的HttpEntity 构造错误(您没有传递标题)。
  • @[chrylis-onstrike]- 我正在尝试 oauth2 客户端,但找不到可用的参考代码,所以我尝试了这个,如果您有任何参考,请与我分享。

标签: java spring curl resttemplate


【解决方案1】:

如果您查看HttpEntity 的文档,您会发现您使用了错误的构造函数。

entity = new HttpEntity<>(reqBodyData, bodyParamMap);

您将要用作正文 (bodyParamMap) 的参数作为标头传递(因为第二个参数是用于请求的标头)。事实上,您甚至没有使用HttpHeaders 来处理请求,因为您没有将它们传递给HttpEntity。我不确定reqBodyData 是什么,但可能是bodyParamMaptoString

你应该做的是以下

entity = new HttpEntity<>(bodyParamMap, headers);

作为HttpHeaders 执行MultiValueMap,您可以直接在构造函数中使用它们。您还想按原样传递bodyParamMap

注意:我还建议在HttpHeaders 上明确设置Content-Type,以便您确定要发送的内容。

headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

因此,生成的总代码应如下所示

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap<String, String> bodyParamMap = new LinkedMultiValueMap<>();
bodyParamMap.add("grant_type", "client_credentials");
bodyParamMap.add("client_id", "nu5yzeth9tektzf5egxuntp7");
bodyParamMap.add("client_secret", "uP2Xvr6SCKYgXgxxJsv2QkUG");

entity = new HttpEntity<>(bodyParamMap, headers);

restTemplate.postForEntity(url, entity, TokenDTO.class)

注意:你不应该构造一个单一的使用RestTemplate,而是你想配置一次并将它注入你的类。

【讨论】:

  • 谢谢@M。 Deinum,我不知道一些事情,你与我分享。虽然,在您回答之前,我已经解决了我的问题,但是您的问题更详细,并且有一些要点,这确实可以帮助其他人。
【解决方案2】:

正如帖子https://stackoverflow.com/a/49127760/11226302所建议的那样

您应该将请求头中的内容类型设置为; headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

希望这会有所帮助!

【讨论】:

    【解决方案3】:

    我刚刚解决了这个问题:

    我有这个

    // wrong
    //private HttpEntity<String> entity;
    

    我改成这样了:

    private MultiValueMap<String, String> parametersMap;
    

    改了

    // not working
    entity = new HttpEntity<>(reqBodyData, bodyParamMap);
    

    到这里

    // working
    entity = new HttpEntity<>(bodyParamMap, headers);
    

    现在一切正常。

    回复:

    2019-12-04 11:52:46,503 DEBUG [restartedMain] org.springframework.core.log.CompositeLog: HTTP POST https://cloudsso.example.com/as/token.oauth2
    2019-12-04 11:52:46,521 DEBUG [restartedMain] org.springframework.core.log.CompositeLog: Accept=[application/json, application/*+json]
    2019-12-04 11:52:46,522 DEBUG [restartedMain] org.springframework.core.log.CompositeLog: Writing [{grant_type=[client_credentials], client_id=[nu5yzeth9tektzf5egxuntp7], client_secret=[uP2Xvr6SCKYgXgxxJsv2QkUG]}] with org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
    2019-12-04 11:52:47,831 DEBUG [restartedMain] org.springframework.core.log.CompositeLog: Response 200 OK
    

    注意:在我的情况下,添加或禁用此值没有任何区别,反正我正在获取身份验证令牌。

    //headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    

    【讨论】:

    • 问题是您将正文作为标头发送到哪里,而不确定reqBodyData 是什么。但由于这个原因,它选择了错误的消息编码器。尽管如此,您最好明确设置内容类型以确保(您也或多或少地使用 curl 使用 -d 做到了这一点)。
    猜你喜欢
    • 1970-01-01
    • 2020-01-29
    • 2018-01-07
    • 2017-04-05
    • 2013-12-26
    • 2019-03-20
    • 2017-08-03
    • 2018-04-16
    相关资源
    最近更新 更多