需要针对密码过期的任何数据源的基于 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
(或者您可以使用任何其他更合适的检查),然后前往 Cyberark 获取实际密码
【参考方案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 的应用程序的通用解决方案的主要内容,如果未能解决你的问题,请参考以下文章
Spring cloud微服务安全实战-_5-10实现基于session的SSO(Token有效期)
Spring Security:会话过期而不重定向到过期网址?