我正在使用 Spring-Boot 2.7.6 以及在 VMWare Tanzu 上运行的 Spring-Cloud 2021.0.5 应用程序, 使用 OAuth2RestTemplate 通过 Feign 客户端通过 Hybris/SAP Commerce 应用程序验证我的 API。 但是,我的 API 间歇性地收到“401 未经授权”(无效令牌错误)异常。
假装界面示例:
@FeignClient(name = "hybris", url = "${URL}", fallbackFactory = HybrisClientFallbackFactory.class, configuration = {
HybrisFeignClientRequestInterceptor.class, FeignRetryConfiguration.class, FeignRetryer.class})
public interface HybrisClient
{
@PostMapping("/epInternal/order/order-history")
OrderHistoryResponse getOrderHistory(OrderHistoryRequest orderHistoryRequest);
}
Feign请求拦截器:
public class HybrisFeignClientRequestInterceptor {
@Qualifier("hybrisOAuth2RestTemplate")
private final OAuth2RestTemplate hybrisOAuth2RestTemplate;
@Bean
public RequestInterceptor apigeeHybrisOauth2RequestInterceptor() {
return (requestTemplate) -> {
requestTemplate.header("Authorization", new String[]{String.format("%s %s", "Bearer", this.hybrisOAuth2RestTemplate.getAccessToken().getValue())});
requestTemplate.header("x-api-key", new String[]{clientId});
};
}
}
上述代码与同一应用程序(在 Prod 中运行)的旧 Spring Boot 版本无缝运行,但在 SB-2.7.6 中间歇性失败。 当它失败时,直到系统重新启动它就会一直失败。
进一步调查发现,它仅在一个实例上失败,同时在应用程序的另一个实例上运行良好,并且当时都使用不同的访问令牌(从日志中找到此信息)
每当 Hybris oauth 令牌响应的 oauth 令牌 expires_in 值为 0(在极少数情况下)时, 旧版本的Spring-security-oauth2(2.4.0及以下)将expiresAt(用于验证令牌的令牌到期日期时间)设置为当前日期, 但是,在上述场景中,Spring-security-oauth2 2.5.0 将 expiresAt 值设置为 null,因此每当 Oauth2RestTemplate 检查令牌有效性时,它都会错误地将其识别为始终有效。因此,在服务重新启动之前,不会调用刷新令牌。
解决方法:
将 Spring-security-oauth2 版本降级至 2.4.0