Spring RestTemplate 收到“401 未经授权”
Spring RestTemplate receives "401 Unauthorized"
我正在使用以下内容通过 Spring 4 中的 RestTemplate 检索 JSON:
protected DocInfoResponse retrieveData(String urlWithAuth) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + auth.getSig());
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<DocInfoResponse> response = restTemplate.exchange(urlWithAuth, HttpMethod.GET, request, DocInfoResponse.class);
return response.getBody();
}
我使用相同的代码(具有不同的响应 class)从同一站点成功获取 JSON 文档(使用不同的参数获取不同的文档)。
当我执行上面的代码时,我收到以下堆栈跟踪(部分):
Caused by: org.springframework.web.client.HttpClientErrorException: 401 Unauthorized
at
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
谁能告诉我为什么这可能会收到异常?
在调查我自己的问题后,我意识到 FireFox RESTClient 是成功的,因为我连接到了目标 URL。我以为我正在使用的基本身份验证毕竟不是那么基本。
最终,我阅读了我尝试连接的应用程序的文档,意识到他们提出了一种连接令牌机制。现在可以了。
阅读你的代码后,我说它看起来还不错,虽然我不确定你调用 getSig
.
的对象 auth
是什么
第一件事:尝试从任何客户端访问您的服务,例如网络浏览器、PostMan 或 RESTClient。确保您在未连接到您的应用程序的情况下成功检索您的信息!!!
根据结果,我说你应该尝试手动加密你的 Authorization
令牌(你会很容易在这个网站上找到向你展示如何加密的帖子)或尝试另一种连接机制。
我发现上面最初发布的问题是由于 auth
参数发生了双重加密。我通过使用 UriComponentsBuilder
并在 exchange()
.
上显式调用 encode()
来解决它
SyncResponse retrieveData(UriComponentsBuilder builder) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<SyncResponse> response = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.GET, request, SyncResponse.class);
return response.getBody();
}
我的 UriComponentsBuilder
是使用以下方法构建的:
UriComponentsBuilder buildUrl(String urlString) {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(urlString);
return auth.appendAuth(builder);
}
(auth.appendAuth()
在 urlString
中添加目标服务所需的额外 .queryParams()
。)
执行此操作的调用是 retrieveData(buildUrl(urlString));
。
创建授权 header 的过程对于基本身份验证来说相对简单,因此几乎可以通过几行代码手动完成:
HttpHeaders createHeaders(String username, String password){
return new HttpHeaders() {{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")) );
String authHeader = "Basic " + new String( encodedAuth );
set( "Authorization", authHeader );
}};
}
那么,发送请求就变得如此简单:
RestTemplate restTemplate = new RestTemplate();
restTemplate.exchange
(uri, HttpMethod.POST, new HttpEntity<T>(createHeaders(username, password)), clazz);
https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring#manual_auth
我正在使用以下内容通过 Spring 4 中的 RestTemplate 检索 JSON:
protected DocInfoResponse retrieveData(String urlWithAuth) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + auth.getSig());
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<DocInfoResponse> response = restTemplate.exchange(urlWithAuth, HttpMethod.GET, request, DocInfoResponse.class);
return response.getBody();
}
我使用相同的代码(具有不同的响应 class)从同一站点成功获取 JSON 文档(使用不同的参数获取不同的文档)。
当我执行上面的代码时,我收到以下堆栈跟踪(部分):
Caused by: org.springframework.web.client.HttpClientErrorException: 401 Unauthorized
at
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
谁能告诉我为什么这可能会收到异常?
在调查我自己的问题后,我意识到 FireFox RESTClient 是成功的,因为我连接到了目标 URL。我以为我正在使用的基本身份验证毕竟不是那么基本。
最终,我阅读了我尝试连接的应用程序的文档,意识到他们提出了一种连接令牌机制。现在可以了。
阅读你的代码后,我说它看起来还不错,虽然我不确定你调用 getSig
.
auth
是什么
第一件事:尝试从任何客户端访问您的服务,例如网络浏览器、PostMan 或 RESTClient。确保您在未连接到您的应用程序的情况下成功检索您的信息!!!
根据结果,我说你应该尝试手动加密你的 Authorization
令牌(你会很容易在这个网站上找到向你展示如何加密的帖子)或尝试另一种连接机制。
我发现上面最初发布的问题是由于 auth
参数发生了双重加密。我通过使用 UriComponentsBuilder
并在 exchange()
.
encode()
来解决它
SyncResponse retrieveData(UriComponentsBuilder builder) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> request = new HttpEntity<String>(headers);
ResponseEntity<SyncResponse> response = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.GET, request, SyncResponse.class);
return response.getBody();
}
我的 UriComponentsBuilder
是使用以下方法构建的:
UriComponentsBuilder buildUrl(String urlString) {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(urlString);
return auth.appendAuth(builder);
}
(auth.appendAuth()
在 urlString
中添加目标服务所需的额外 .queryParams()
。)
执行此操作的调用是 retrieveData(buildUrl(urlString));
。
创建授权 header 的过程对于基本身份验证来说相对简单,因此几乎可以通过几行代码手动完成:
HttpHeaders createHeaders(String username, String password){
return new HttpHeaders() {{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")) );
String authHeader = "Basic " + new String( encodedAuth );
set( "Authorization", authHeader );
}};
}
那么,发送请求就变得如此简单:
RestTemplate restTemplate = new RestTemplate();
restTemplate.exchange
(uri, HttpMethod.POST, new HttpEntity<T>(createHeaders(username, password)), clazz);
https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring#manual_auth