请注意下面的代码和 sessionManager() 方法,我在其中将侦听器“VaultEventListener”添加到会话中。下面还提供了 VaultEventListener 类代码。 我的要求是,每当调用更新现有令牌时出现错误,每当出现令牌更新错误时都会调用保管库事件侦听器,以便我可以重试多次尝试。
class SntlVaultGcpIamAuthConfig extends AbstractVaultConfiguration {
static final Logger logger = LogManager.getLogger(SntlVaultGcpIamAuthConfig.class);
@Override
public ClientAuthentication clientAuthentication() {
try {
GoogleCredentials credential = GoogleCredentials.getApplicationDefault();
String account = null;
if (credential instanceof ServiceAccountCredentials) {
account = ((ServiceAccountCredentials) credential).getAccount();
} else if (credential instanceof ComputeEngineCredentials) {
account = ((ComputeEngineCredentials) credential).getAccount();
} else {
logger.fatal(
"Unable to get service account email, Application default GoogleCredentials must be instance of ServiceAccountCredentials or ComputeEngineCredentials");
return null;
}
logger.info("Application running with service account : {}", account);
GcpIamCredentialsAuthenticationOptions options = GcpIamCredentialsAuthenticationOptions.builder()
.role(SntlVaultConfig.getGcpVaultLoginRole()).credentials(credential).serviceAccountId(account)
.build();
GcpIamCredentialsAuthentication authN = new GcpIamCredentialsAuthentication(options, this.restOperations());
return authN;
} catch (IOException | SntlCloudEnvException e) {
logger.fatal( "An exception occurred in setting up GCP IAM authentication for Vault.", e);;
}
return null;
}
@Override
public VaultEndpoint vaultEndpoint() {
VaultEndpoint endPoint = new VaultEndpoint();
try {
endPoint.setHost(SntlVaultConfig.getVaultAddr());
endPoint.setPort(SntlVaultConfig.getVaultPort());
endPoint.setScheme(SntlVaultConfig.getVaultEndPointScheme());
return endPoint;
} catch (SntlCloudEnvException e) {
logger.fatal( "SntlCloudEnvException occurred .", e);
return null;
}
}
@Override
public ClientOptions clientOptions() {
try {
return new ClientOptions(Duration.ofSeconds(SntlVaultConfig.getVaultConnectionTimeout()), Duration.ofSeconds(SntlVaultConfig.getVaultReadTimeout()));
} catch (SntlCloudEnvException e) {
logger.fatal( "SntlCloudEnvException occurred .", e);
return null;
}
}
@Override
@Bean
@Primary
public SessionManager sessionManager() {
boolean retryEnabled = Boolean.parseBoolean(SntlVaultConfig.isRetryTokenRenewal);
int REFRESH_PERIOD_BEFORE_EXPIRY = Integer.parseInt(SntlVaultConfig.refreshBeforeExpiryDuration); //120; // Overrides default which is 5 seconds
ClientAuthentication clientAuthentication = clientAuthentication();
Assert.notNull(clientAuthentication, "ClientAuthentication must not be null");
LifecycleAwareSessionManagerSupport.FixedTimeoutRefreshTrigger refreshTrigger = new LifecycleAwareSessionManagerSupport.FixedTimeoutRefreshTrigger(
REFRESH_PERIOD_BEFORE_EXPIRY, TimeUnit.SECONDS);
LifecycleAwareSessionManager lifecycleAwareSessionManager = new LifecycleAwareSessionManager(clientAuthentication, getVaultThreadPoolTaskScheduler(), restOperations(), refreshTrigger);
lifecycleAwareSessionManager.setLeaseStrategy(LeaseStrategy.retainOnError()); //To-validate
VaultEventListener vaultEventListener = new VaultEventListener();
lifecycleAwareSessionManager.addErrorListener(vaultEventListener);
return lifecycleAwareSessionManager;
}
public class VaultEventListener implements AuthenticationErrorListener {
private static final Logger logger = LoggerFactory.getLogger(VaultEventListener.class);
@Override
public void onAuthenticationError(AuthenticationErrorEvent event) {
logger.info("AuthenticationErrorListener Error Source: {}", event.getSource());
logger.info("AuthenticationErrorListener Exception: {}", event.getException());
if (Boolean.parseBoolean(SntlVaultConfig.isRetryTokenRenewal)) {
AnnotationConfigApplicationContext context = SntlCloudEnvContext.getContext();
SntlVaultGcpIamAuthConfig sntlVaultGcpIamAuthConfig = context.getBean(SntlVaultGcpIamAuthConfig.class);
sntlVaultGcpIamAuthConfig.refreshToken();
}
}
}
公共类 VaultEventListener 实现 AuthenticationErrorListener {
private static final Logger logger = LoggerFactory.getLogger(VaultEventListener.class);
private final SntlVaultGcpIamAuthConfig vaultConfig;
public VaultEventListener(SntlVaultGcpIamAuthConfig vaultConfig) {
this.vaultConfig = vaultConfig;
}
@Override
public void onAuthenticationError(AuthenticationErrorEvent event) {
logger.info("AuthenticationErrorListener Error Source: {}", event.getSource());
logger.info("AuthenticationErrorListener Exception: {}", event.getException());
if (Boolean.parseBoolean(SntlVaultConfig.isRetryTokenRenewal)) {
int maxRetryAttempts = 3; // Define the maximum number of retry attempts
for (int attempt = 1; attempt <= maxRetryAttempts; attempt++) {
logger.info("Attempting token renewal retry, attempt: {}", attempt);
try {
vaultConfig.refreshToken(); // Assuming refreshToken() retries internally on error
break; // Exit loop if renewal succeeds
} catch (Exception e) {
logger.error("Token renewal retry failed, attempt: {}", attempt, e);
// Log the error and retry
}
}
}
}
} VaultEventListener 类中,onAuthenticationError 方法实现了令牌更新的简单重试机制。它会重试刷新令牌方法,直至达到最大尝试次数 (maxRetryAttempts)。如果更新成功,则跳出重试循环;否则,它将继续重试,直到达到最大尝试次数。
您需要修改 SntlVaultGcpIamAuthConfig 类中的 sessionManager 方法,以将 SntlVaultGcpIamAuthConfig 的实例传递给 VaultEventListener 构造函数:
VaultEventListenerVaultEventListener = new VaultEventListener(this); lifecycleAwareSessionManager.addErrorListener(vaultEventListener);