需要针对密码过期的任何数据源的基于 Spring 的应用程序的通用解决方案

Posted

技术标签:

【中文标题】需要针对密码过期的任何数据源的基于 Spring 的应用程序的通用解决方案【英文标题】:Need generic solution for Spring based app for any Data source on Password expire 【发布时间】:2018-11-22 13:59:49 【问题描述】:

我不知道,如何为以下场景找到解决方案。

我们有一项新要求,即从属性中删除数据库密码,即使它已使用 Jasypt 库或其他一些算法进行加密。

我们需要从 Cyberark 动态获取密码,而不是将密码存储在属性或 LDAP 中。

密码可能在一两天后或一周或一个月后过期。这完全取决于密码过期策略。

我们有多个项目。有些是基于网络的,有些是独立的。我们想写一个通用的解决方案。

如何覆盖任何数据源的getConnection方法,如Spring数据源、Apache Basic数据源(支持扩展类)、C3P0、DBCP或HikariCP,而不影响它们的行为和设置密码在点击super.getConnection()之前?

super.getConnection(); // Here max attempt  will be 3

Spring支持方法替换,但不知道对连接池框架会有什么影响。

如果您需要更多详细信息,请告诉我。

【问题讨论】:

首先,这个要求很好——在源代码中“加密”密码是一种天真的解决方案,不会增加安全性——你的加密密码必须以明文形式解密;你的安全团队做得很好。 至于你目前的问题,包起来吧!创建一个PasswordRenewalDatasource 并包装数据数据库的本机Datasource - 当密码到期时(最好是在它到期之前)更新底层Datasrouce。将PasswordRenewalDatasource 传递到您的连接池。 谢谢鲍里斯,这就是我目前正在做的事情,但是如果我想使用上面提到的数据连接池库,那么我不知道如何实现这一点,或者更确切地说会产生什么影响。 正如我所说,只需将您的池传递给该池!对于 Hikari CP,请使用 dataSourceClassName - 然后正常配置,您都需要传递更新属性。 如果您从属性文件加载数据源属性,您可以使用 AOP 并为Properties.load() 创建方面。 Aspect 将检查属性名称中是否包含password(或者您可以使用任何其他更合适的检查),然后前往 Cyber​​ark 获取实际密码 【参考方案1】:

要解决您的问题,您可以使用 spring-cloud-context 库及其@RefreshScope 注释。另外,你需要发展一点。

1) 你需要一个特殊的 watcher bean 来监控密码是否被更改。会是这样的:

@Service
public class Watcher 
    private final ContextRefresher refresher;

    public Watcher(ContextRefresher refresher) 
        this.refresher = refresher;
    

    @Scheduled(fixedDelay = 10000L)
    public void monitor() 
        if (/* smth changed*/) 
            refresher.refresh();
        
    

因此,当您调用 refresher.refresh(); 时,所有带有 @RefreshContext 注释的 bean 都将在第一次访问它们后被释放和重新创建。

2) 使用 @RefreshContext 注释来注释您的数据源 bean。 3) 您必须提供密码才能使用@ConfigurationProperties 注释访问。您将需要创建 SourceLocator。会是这样的

@Order(0)
public class SourceLocator implements PropertySourceLocator 
    @Override
    public PropertySource<?> locate(Environment environment) 
        //Load properties to hash map
        return new MapPropertySource("props", new HashMap<>());
    

另外,创建一个文件 spring.factories 并将以下数据放在那里:

org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.test.YourSourceLocator

4) 创建属性类,您的数据库通行证将被保存和刷新。

@RefreshScope
@ConfigurationProperties(prefix="your.prefix")
public class Properties 
    private String dbPassword;

将此 bean 自动装配到您创建数据源并使用其中的密码的配置。

【讨论】:

如果问题是特定于 Spring 框架的,您不应该开始引入 Cloud,并通过传递依赖项、引导依赖项。从长远来看,IT 会搞砸你。此外,还为 Spring Cloud 配置服务器创建了刷新范围。更好的解决方案是将数据源包装在另一个数据源 impl 中以在调用失败时刷新并使用刷新的凭据重新尝试。 @RefreshScope 不仅仅用于配置服务器。 Spring-cloud-config 只是使用相同的方法。包装获取配置到数据源的逻辑并不是一个好主意。相反,最好有相同的 Watcher,它将监视更改并设置新密码和softReset() 数据源。但在这种情况下,您必须使用 com.mchange.v2.c3p0.ComboPooledDatasource 感谢 Krauchanka 的回答,但我只想在新获取连接无法加载连接时获取密码,然后想尝试使用新密码和最大尝试 3,因此无法进入循环。

以上是关于需要针对密码过期的任何数据源的基于 Spring 的应用程序的通用解决方案的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE设置用户密码不过期

Spring cloud微服务安全实战-_5-10实现基于session的SSO(Token有效期)

Spring Security:会话过期而不重定向到过期网址?

spring-redis SortedSet类型成员的过期时间处理

linux免密登录secure报密码过期

在基于 Spring 的 Web 应用程序中处理会话过期事件