【问题标题】:Setting Authorization header in Spring RestTemplate在 Spring RestTemplate 中设置授权标头
【发布时间】:2018-10-12 18:00:19
【问题描述】:

我正在尝试借助 Spring 的 RestTemplate 访问 RestAPI-Endpoint

public List<Transaction> getTransactions() {
    // only a 24h token for the sandbox, so not security critical
    // still I replaced the last 10 digits here with 'x' but not in my original code
    String authToken = "tylhtvGM6Duy8q0ZBbGaTg2FZefLfyeEeMZvCXlU2bEiinnZcLSACTxxxxxxxxxx";
    String encodedAuthToken = Base64.getEncoder().encodeToString(authToken.getBytes());

    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    headers.add("Authorization", "Bearer "+encodedAuthToken );

    ResponseEntity<TransactionsResponse> response = restTemplate.exchange(
            "https://api-sandbox.starlingbank.com/api/v1/transactions",
            HttpMethod.GET,
            new HttpEntity<>("parameters", headers),
            TransactionsResponse.class
    );

    return response.getBody().getEmbedded().getTransactions();
}

但我得到一个 HttpClientErrorException 说“403 Forbidden”。 长版

Caused by: org.springframework.web.client.HttpClientErrorException: 403 Forbidden
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79) ~[spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) ~[spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:766) ~[spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]

我的代码基于former stackoverflow thread,并且通过 Postman 使用相同参数的调用成功:

那么问题出在哪里?

更新

不编码 authToken 没有区别

headers.add("Authorization", "Bearer tylhtvGM6Duy8q0ZBbGaTg2FZefLfyeEeMZvCXlU2bEiinnZcLSACTxxxxxxxxxx");

仍然导致同样的HttpClientErrorException: 403 Forbidden

更新2

我回答了我的问题! (短版:需要 UserAgent。anwser 中的最终代码)

【问题讨论】:

  • 在文档link 中说这个 Http 状态代码 403 = Forbidden 您的身份验证失败,通常是由于访问令牌已过期或尝试访问超出令牌范围的资源。您是否有对此范围具有权限的令牌?还是在这两种情况下都使用相同的令牌?
  • 正如您在 Postman 屏幕截图中看到的那样,我使用相同的 authToken。而且我现在仍然使用 Postman 成功,所以令牌在几个小时内仍然有效(之后我可以简单地更新它)。

标签: spring authorization resttemplate


【解决方案1】:

这个特定的服务器需要一个 UserAgent!值可以是任何值,但必须存在!

所以最终版本是:

public List<Transaction> getTransactions() {
    // only a 24h token for the sandbox, so not security critical
    // still I replaced the last 10 digits here with 'x' but not in my original code
    String authToken = "tylhtvGM6Duy8q0ZBbGaTg2FZefLfyeEeMZvCXlU2bEiinnZcLSACTxxxxxxxxxx";

    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));        
    headers.add("User-Agent", "Spring's RestTemplate" );  // value can be whatever
    headers.add("Authorization", "Bearer "+authToken );

    ResponseEntity<TransactionsResponse> response = restTemplate.exchange(
            "https://api-sandbox.starlingbank.com/api/v1/transactions",
            HttpMethod.GET,
            new HttpEntity<>("parameters", headers),
            TransactionsResponse.class
    );

    return response.getBody().getEmbedded().getTransactions();
}

【讨论】:

  • 谢谢,伙计 :) 你的回答拯救了我的一天......已经挣扎了两天
【解决方案2】:

您正在使用 Base64 编码您的令牌,并且它已经编码,您的代码基于 this,但在此示例中,它们使用 (user:password) 编码的基本授权标头进行编码

探索这个

 HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    headers.add("Authorization", "Bearer "+ authToken );

【讨论】:

  • 没有区别 :( (这就是我开始的 - 现在又回到 - 我仍然导致 403
【解决方案3】:

如果您使用 OAuth Bearer 令牌进行身份验证,则无需在发出请求之前对其进行编码。下面一行就足够了:

headers.add("Authorization", "Bearer " + authToken);

您提到的代码具有 Http Basic 身份验证,其中包括将凭据发送为使用 Base64 编码的username:password 对。

【讨论】:

  • 我更新了正文,说这没有什么区别。所以我回到了你提到的版本——没有额外的编码步骤——但结果是一样的。
  • 您确定令牌仍然有效,没有过期吗?
  • 100% (每个token的有效期只有24小时,所以我只是第三次更新它,将它复制到我的代码中,运行mvn clean然后执行代码,仍然导致403 禁止)
【解决方案4】:

对于Bearer身份验证 Spring有一个方便的方法setBearerAuth(String token),从5.1版本开始:

// anonymised: replaced the last 10 digits here with 'x'
String authToken = "tylhtvGM6Duy8q0ZBbGaTg2FZefLfyeEeMZvCXlU2bEiinnZcLSACTxxxxxxxxxx";
HttpHeaders headers = new HttpHeaders();

headers.setBearerAuth(authToken);

【讨论】:

    猜你喜欢
    • 2021-06-20
    • 2017-08-18
    • 2017-08-30
    • 2021-11-21
    • 2015-12-02
    • 2018-01-14
    • 1970-01-01
    • 2017-12-03
    • 2021-04-07
    相关资源
    最近更新 更多