Spring RestTemplate收到" 401 Unauthorized"

时间:2017-03-11 22:06:38

标签: spring spring-boot resttemplate spring-rest

我使用以下内容在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();
}

我使用相同的代码(具有不同的响应类)来成功从同一站点获取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]

有人能指出为什么这可能会收到例外吗?

3 个答案:

答案 0 :(得分:1)

我发现我上面发布的问题原因是auth参数上发生了双重加密。我使用UriComponentsBuilder并在encode()上明确调用exchange()来解决此问题。

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()在[{1}}中添加了目标服务所需的额外.queryParams()。)

执行此操作的调用是urlString

答案 1 :(得分:0)

在调查我自己的问题后,我意识到FireFox RESTClient成功,因为我已连接到目标URL。我认为我使用的Basic Auth毕竟不是那么基本。

最后,我阅读了我试图连接到的应用程序的文档,并意识到他们提出了一种连接令牌机制。现在它有效。

在阅读完代码后,我说它看起来很不错,但我不确定您调用import seaborn as sns df = ... # My dataset g = sns.PairGrid(df, hue="value", palette=sns.light_palette("red", len(df)), hue_order=sorted(df["value"]), vars=df.columns[:-1]) g.map_diag(lambda x, **kwargs: sns.stripplot(x, x, **kwargs), jitter=True) g.map_offdiag(sns.stripplot, jitter=True) 的对象auth是什么。

首先要做的事情:尝试从任何客户端访问您的服务,例如Web浏览器,PostMan或RESTClient。确保您没有连接到您的应用程序就成功检索了您的信息!

根据结果,我说您应该尝试手动加密getSig令牌(您可以轻松找到此网站上的帖子向您展示如何)或尝试其他连接机制。

答案 2 :(得分:0)

对于基本身份验证而言,创建Authorization标头的过程相对简单,因此只需几行代码即可手动完成:

 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