【问题标题】:Spring Boot - How to handle expired access token (custom implementation returns 500 and not 401)Spring Boot - 如何处理过期的访问令牌(自定义实现返回 500 而不是 401)
【发布时间】:2021-04-26 07:32:20
【问题描述】:

我有一个使用休息模板访问休息服务的 Spring Boot 应用程序。 此服务需要访问令牌才能为您提供响应 (200 OK)。

如果令牌已过期而不是 401,服务将返回 500 Internal Server Error。

因为这是一个我无法说服/要求他们返回 401 的系统,所以我无法使用经典的 HTTP 拦截器根据响应状态获取新令牌。

获取新令牌并重试出现 500 Internal Server Error 的调用的最佳方法是什么? 我应该使用 ControllerAdvise 吗?我是 spring 新手,我对“正确”的机制有点困惑。

【问题讨论】:

  • 除了 HTTP 状态码 500 之外,它是否为您提供任何其他详细信息?
  • @sonus21 他提供了某些消息“令牌已在 bla bla 上过期”或“无效令牌 bla bla”。

标签: spring-boot access-token resttemplate


【解决方案1】:

我建议,当你得到一个500时,请检查异常类型并检查其他参数(系统错误代码,描述)。如果异常类型与AuthenticationException / Access Denied有关,那么你可以尝试重试机制。

简单的伪代码会是这样的。

   if(Http.Status_Code== 500){
           if(Exception instance of AuthenticationException){
                   //call to get the access token
                   // call the service again
                } 
            }

另外,您检查 Spring 重试机制,

Spring 重试注解

@EnableRetry – 在 Spring Boot 项目中启用 Spring 重试

@Retryable – 表示任何方法都可以重试

@Recover – 指定备用方法!

https://howtodoinjava.com/spring-boot2/spring-retry-module/

https://docs.spring.io/spring-batch/docs/current/reference/html/retry.html

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.3.1</version>
</dependency>

【讨论】:

  • 感谢您的回复。伪代码应该放在 ControllerAdvise 方法中吗?或者它可以是原始休息控制器中的尝试捕获?现在我在实现逻辑的控制器中有一个 try catch 块(在重试调用之前捕获 500 并检查消息并获取新令牌)。
  • 您可以在 try-catch 块中使用。但是使用spring Retry的内置库的好方法。如果你想使用它,你也可以考虑使用 Hystrix。您可以在 kafka(消息系统)中检查 DLQ 实现,当任何 API 调用失败时,将消息推送到 DLQ 并再次消费以调用服务。
  • 感谢您的宝贵时间和评论。
  • 如果你觉得答案有用,你可以接受它,它也会对其他人有帮助。
  • 将在帖子保留一段时间后执行(如果这是公认的答案,有时可能会阻止其他人发表意见)。
【解决方案2】:

Spring Retry 非常适合您的用例。

我假设你得到AuthenticationException 异常。

这是控制器级别的示例代码。

@Retryable(value = { AuthenticationException.class }, maxAttempts = 4, backoff = @Backoff(500))
@GetMapping("/testRetry")
public String loadData(@RequestParam("id") int id) {
    //your code
    return "Success";
}

@Recover  
public String recover(AuthenticationException t, int d) {
    System.out.println("recover method called");
    return "Error";
}

您也可以使用@Recover 阻止,以防所有重试尝试都用尽。 backoff 将在重试之前等待 500 ms

更多详情请参考here

【讨论】:

  • 感谢您的宝贵时间。
猜你喜欢
  • 2020-11-09
  • 1970-01-01
  • 2021-10-07
  • 2019-05-25
  • 2021-09-06
  • 2018-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多