Postman 和 RestTemplate 的 API 调用中的 body 参数相同,但只有 Postman 有效
Same body parameters in Postman and RestTemplate's API call but only Postman works
我的应用程序使用 Spotify 的 API 直到几天前才正常工作,但是,突然它告诉我我正在使用的 body 参数之一是错误的(与以前工作过)。
我在 Postman 中测试了这个相同的参数,它工作得很好:
Postman call
Body 产生错误的参数:
grant_type: authorization_code
我收到的回复消息:
400 Bad Request
{
"error": "unsupported_grant_type",
"error_description": "grant_type must be client_credentials, authorization_code or refresh_token"
}
我已经放置了一个拦截器来检查我进行的调用是否真的有正确的参数并且它确实正确显示。
我使用的代码:
休息电话
RestTemplate template = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", CLIENT_ID_SECRET);
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("grant_type", "authorization_code"); //parameter generating the error
map.add("code", CODE);
map.add("redirect_uri", "https://www.getpostman.com/oauth2/callback");
HttpEntity<MultiValueMap<String, String>> requestEntity=
new HttpEntity<MultiValueMap<String, String>>(map, headers);
try{
AccessToken accessToken = template.postForObject("https://accounts.spotify.com/api/token/", requestEntity, AccessToken.class);
}
catch(RestClientResponseException e) {
System.out.println(e.getMessage());
System.out.println("Fail " + e.getResponseBodyAsString());
}
拦截器结果:
2019-08-29 23:37:44.660 INFO 18784 --- [nio-8080-exec-3] c.e.d.helper.LoggingRequestInterceptor : URI : https://accounts.spotify.com/api/token/
2019-08-29 23:37:44.664 INFO 18784 --- [nio-8080-exec-3] c.e.d.helper.LoggingRequestInterceptor : Method : POST
2019-08-29 23:37:44.665 INFO 18784 --- [nio-8080-exec-3] c.e.d.helper.LoggingRequestInterceptor : Headers : [Accept:"application/json, application/*+json", Content-Type:"application/x-www-form-urlencoded;charset=UTF-8", Authorization:"Basic M2JjZDNmMDVmYTBiNDVkOWE4MTY4ZmFmMjNhYj...DdiMmJjODg=", Content-Length:"433"]
2019-08-29 23:37:44.666 INFO 18784 --- [nio-8080-exec-3] c.e.d.helper.LoggingRequestInterceptor : Request body: grant_type=authorization_code&code=AQCTD5keYruiGP1ukaZYhDcC0tu9eLnvPnt3IYGlk7mfyaMIPEtdAiTCGbJOfpFA0v9-kgDJJysMAfTnx2e76AHbOZ2C55WVMtYvrR88t6_MDAkbLaPI_0NK7u8AqWhfj1zrkUz-3PBVwoPs6PduuqucSJporVEedpdcNGuQ24HjJdBxjQNEuBwGeTIllBkaWZSx6RzKoZcU-IPw5M44EbCwvHOtZiWL4U5nzER3NPCiZ9_r_w__wmFW1-HunE-32Q1lBzNz9vJVvsl3X_vumBHCNCAWdITzAmiUdU34RHRQAnyimKMPsnPYA-fd1Y_a47e2EXCJclgTHgm6-ODEXmZB&redirect_uri=https%3A%2F%2Fwww.getpostman.com%2Foauth2%2Fcallback
我不知道要测试什么了,非常感谢任何帮助。
编辑:
我发现了问题,
我正在向 https://accounts.spotify.com/api/token/ 提出请求
删除最终的/有效的(https://accounts.spotify.com/api/token)。
很可能它被更改为最终使用 / 向其他端点发出请求,因为 https://api.spotify.com/v1/me/ 仍然有效...
现在我已经在 Spotify
中登录并创建了一个应用程序。请找到以下对我来说工作正常的来源。我在您的来源中找不到任何错误。
授权
代币
@GetMapping("/spotify-response")
public void spotifyResponse(@RequestParam String code, HttpServletResponse httpServletResponse) {
String _clientId = "5eb8ce6ea7d04*******e870c48f";
String _clientSecret = "d45470deea224********3d8ab9";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
String usernamePassword = _clientId+":"+_clientSecret;
String basicToken = Base64.getEncoder().encodeToString(usernamePassword.getBytes());
httpHeaders.set("Authorization", "Basic "+basicToken);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", "authorization_code");
requestBody.add("code", code.trim());
requestBody.add("redirect_uri", "http://localhost:11001/api/spotify-response");
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(requestBody, httpHeaders);
try {
Object response = restTemplate.postForObject("https://accounts.spotify.com/api/token", httpEntity, Object.class);
Map<String, Object> map = (Map<String, Object>) response;
map.forEach((k, v) -> System.out.println(k+": "+v));
httpServletResponse.setStatus(302);
String accessToken = (String) map.get("access_token");
String patientId = (String) map.get("patient");
String url = "http://localhost:4200/login-success?accessToken="+accessToken+"&patientId="+patientId;
httpServletResponse.setHeader("Location", url); // redirect to success page
}
catch(HttpClientErrorException e) {
e.printStackTrace();
}
}
控制台输出:
access_token: BQB9z1CeXwnS3MI0uQN-eAK9WRIW4r7U5k0H1RCxnRi5UlF04oYbcYgyoFH3wM-EQUydkKhXjhlJOposaoYSssQpcF9HgPHVCPiwNvzrHS5H8Cc64gcFlstAKxFDTMAfyUqfQ4UTBvdGfmQoORxoEhzsGCAcps-3fnoca_XdzLgjfJdPaQ
token_type: Bearer
expires_in: 3600
refresh_token: AQCKahUnfekyvGZ3RuO6h85YPSmhCqlRTklCw8r4RZzh8BesCu-4mVXKypsuTNV7AwE5tRJt8BXDn1eyXf797LvfVfN4Ju4KUc9AzYFKOiQPblUMip3_ImPOZDsF1InxIzjkAA
scope: user-read-private
我的应用程序使用 Spotify 的 API 直到几天前才正常工作,但是,突然它告诉我我正在使用的 body 参数之一是错误的(与以前工作过)。 我在 Postman 中测试了这个相同的参数,它工作得很好: Postman call
Body 产生错误的参数: grant_type: authorization_code
我收到的回复消息:
400 Bad Request
{
"error": "unsupported_grant_type",
"error_description": "grant_type must be client_credentials, authorization_code or refresh_token"
}
我已经放置了一个拦截器来检查我进行的调用是否真的有正确的参数并且它确实正确显示。
我使用的代码:
休息电话
RestTemplate template = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", CLIENT_ID_SECRET);
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("grant_type", "authorization_code"); //parameter generating the error
map.add("code", CODE);
map.add("redirect_uri", "https://www.getpostman.com/oauth2/callback");
HttpEntity<MultiValueMap<String, String>> requestEntity=
new HttpEntity<MultiValueMap<String, String>>(map, headers);
try{
AccessToken accessToken = template.postForObject("https://accounts.spotify.com/api/token/", requestEntity, AccessToken.class);
}
catch(RestClientResponseException e) {
System.out.println(e.getMessage());
System.out.println("Fail " + e.getResponseBodyAsString());
}
拦截器结果:
2019-08-29 23:37:44.660 INFO 18784 --- [nio-8080-exec-3] c.e.d.helper.LoggingRequestInterceptor : URI : https://accounts.spotify.com/api/token/
2019-08-29 23:37:44.664 INFO 18784 --- [nio-8080-exec-3] c.e.d.helper.LoggingRequestInterceptor : Method : POST
2019-08-29 23:37:44.665 INFO 18784 --- [nio-8080-exec-3] c.e.d.helper.LoggingRequestInterceptor : Headers : [Accept:"application/json, application/*+json", Content-Type:"application/x-www-form-urlencoded;charset=UTF-8", Authorization:"Basic M2JjZDNmMDVmYTBiNDVkOWE4MTY4ZmFmMjNhYj...DdiMmJjODg=", Content-Length:"433"]
2019-08-29 23:37:44.666 INFO 18784 --- [nio-8080-exec-3] c.e.d.helper.LoggingRequestInterceptor : Request body: grant_type=authorization_code&code=AQCTD5keYruiGP1ukaZYhDcC0tu9eLnvPnt3IYGlk7mfyaMIPEtdAiTCGbJOfpFA0v9-kgDJJysMAfTnx2e76AHbOZ2C55WVMtYvrR88t6_MDAkbLaPI_0NK7u8AqWhfj1zrkUz-3PBVwoPs6PduuqucSJporVEedpdcNGuQ24HjJdBxjQNEuBwGeTIllBkaWZSx6RzKoZcU-IPw5M44EbCwvHOtZiWL4U5nzER3NPCiZ9_r_w__wmFW1-HunE-32Q1lBzNz9vJVvsl3X_vumBHCNCAWdITzAmiUdU34RHRQAnyimKMPsnPYA-fd1Y_a47e2EXCJclgTHgm6-ODEXmZB&redirect_uri=https%3A%2F%2Fwww.getpostman.com%2Foauth2%2Fcallback
我不知道要测试什么了,非常感谢任何帮助。
编辑:
我发现了问题, 我正在向 https://accounts.spotify.com/api/token/ 提出请求 删除最终的/有效的(https://accounts.spotify.com/api/token)。 很可能它被更改为最终使用 / 向其他端点发出请求,因为 https://api.spotify.com/v1/me/ 仍然有效...
现在我已经在 Spotify
中登录并创建了一个应用程序。请找到以下对我来说工作正常的来源。我在您的来源中找不到任何错误。
授权
代币
@GetMapping("/spotify-response")
public void spotifyResponse(@RequestParam String code, HttpServletResponse httpServletResponse) {
String _clientId = "5eb8ce6ea7d04*******e870c48f";
String _clientSecret = "d45470deea224********3d8ab9";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
String usernamePassword = _clientId+":"+_clientSecret;
String basicToken = Base64.getEncoder().encodeToString(usernamePassword.getBytes());
httpHeaders.set("Authorization", "Basic "+basicToken);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("grant_type", "authorization_code");
requestBody.add("code", code.trim());
requestBody.add("redirect_uri", "http://localhost:11001/api/spotify-response");
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(requestBody, httpHeaders);
try {
Object response = restTemplate.postForObject("https://accounts.spotify.com/api/token", httpEntity, Object.class);
Map<String, Object> map = (Map<String, Object>) response;
map.forEach((k, v) -> System.out.println(k+": "+v));
httpServletResponse.setStatus(302);
String accessToken = (String) map.get("access_token");
String patientId = (String) map.get("patient");
String url = "http://localhost:4200/login-success?accessToken="+accessToken+"&patientId="+patientId;
httpServletResponse.setHeader("Location", url); // redirect to success page
}
catch(HttpClientErrorException e) {
e.printStackTrace();
}
}
控制台输出:
access_token: BQB9z1CeXwnS3MI0uQN-eAK9WRIW4r7U5k0H1RCxnRi5UlF04oYbcYgyoFH3wM-EQUydkKhXjhlJOposaoYSssQpcF9HgPHVCPiwNvzrHS5H8Cc64gcFlstAKxFDTMAfyUqfQ4UTBvdGfmQoORxoEhzsGCAcps-3fnoca_XdzLgjfJdPaQ
token_type: Bearer
expires_in: 3600
refresh_token: AQCKahUnfekyvGZ3RuO6h85YPSmhCqlRTklCw8r4RZzh8BesCu-4mVXKypsuTNV7AwE5tRJt8BXDn1eyXf797LvfVfN4Ju4KUc9AzYFKOiQPblUMip3_ImPOZDsF1InxIzjkAA
scope: user-read-private