如何将 OS 环境变量连接到 Spring Web 应用程序项目中 application.properties 中的占位符?

Posted

技术标签:

【中文标题】如何将 OS 环境变量连接到 Spring Web 应用程序项目中 application.properties 中的占位符?【英文标题】:How to connect OS environment variables to placeholders in application.properties in a Spring Web app project? 【发布时间】:2019-12-23 16:45:45 【问题描述】:

1) 我创建了提到的环境文件here

我创建了一个名为Prod.env 的文件并输入了以下内容

SPRING_DATASOURCE_URL="jdbc:mysql://5.6.7.8:3306/ab?autoReconnect=true&characterEncoding=utf8"
SPRING_DATASOURCE_USERNAME="root"
SPRING_DATASOURCE_PASSWORD="IWin"

然后我执行了这个命令export $(cat Prod.env | xargs)

2) 然后我用下面的代码在WEB-INF 下创建了application.properties

spring.datasource.driver-class-name:com.mysql.jdbc.Driver
spring.datasource.url=$SPRING_DATASOURCE_URL
spring.datasource.username=$SPRING_DATASOURCE_USERNAME
spring.datasource.password=$SPRING_DATASOURCE_PASSWORD

3) 然后在spring-security.xml

  <b:bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <b:property name="location">
            <b:value>/WEB-INF/application.properties</b:value>
        </b:property>
  </b:bean> 
  <b:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <b:property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
        <b:property name="url" value="$spring.datasource.url" />
        <b:property name="username" value="$spring.datasource.username" />
        <b:property name="password" value="$spring.datasource.password" />
  </b:bean>

现在,当我保存所有内容并重新启动时,我得到了

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in ServletContext resource [/WEB-INF/spring/appServlet/spring-security.xml]: Could not resolve placeholder 'SPRING_DATASOURCE_URL' in string value "jdbc:mysql:$SPRING_DATASOURCE_URL"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'SPRING_DATASOURCE_URL' in string value "jdbc:mysql:$SPRING_DATASOURCE_URL"

我想要实现的是: 通过 application.properties 访问环境变量(或在 spring-security.xml 中进行一些配置),但不能使用 java 代码。我在这里错过了什么?

我搜索了几个问题,但没有一个解释清楚。请帮忙

注意:我的不是 Spring Boot 项目。这是普通的 Spring 4.0.3 web 应用程序。

【问题讨论】:

您可能已经知道,每次打开终端时都必须运行export 命令。要保留这些环境变量,请将它们添加到 .profile 或 .bashrc。将明文密码保存到环境变量或纯文本文件中,这是一个很大的安全问题。 @LuisMuñoz 那么如何设置环境变量而不在文本文件中输入密码。如果我使用散列密码并将其放入文本文件中,然后设置 enn vars,则每次使用加密密码时,我都必须对其进行解密。除了这些还有其他选择吗? jasypt.org/spring3.html 看起来是个不错的选择。 好的。我想一次解决问题。我首先计划将 env 变量添加到 bash shell 中,以便永久添加,而不必每次都设置它。为此,我正在关注 unix.stackexchange.com/questions/117467/… --> 我打开 /etc/profile 并将 export $(cat Prod.env | xargs) 添加为最后一行,然后保存并重新启动 bash。我在那里看不到那些变量。如何永久设置环境变量,以便每次打开终端时都不必运行导出命令 最好在您的家庭个人资料$HOME/.profile 上执行此操作。每个用户都可以使用另一种方式的密码;)。只需为每个 var 添加一个 export,不包括 cat 和其他东西。然后运行source $HOME/.profile 或退出登录。 【参考方案1】:

通常的做法是应用程序不应该知道环境类型(ENV、INTP、PROD等)的任何信息。这意味着,不指定环境(阶段)名称,而是使用相同的名称 属性文件,将所需版本的文件放入类路径。例如,在 DEV 环境中,您将 application.properties 的 DEV 版本放入类路径,在 PROD 环境中,您将 application.properties 的 PROD 版本放入类路径。

在您的情况下,我建议您从 WEB-INF 中删除 application.properties 并将其放在 WAR 之外(如果您使用 EAR,也在 EAR 之外)。把它放到你的应用的classpath或者应用服务器的classpath中,配置你的bean如下:

  <b:bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <b:property name="location">
            <b:value>classpath*:application.properties</b:value>
        </b:property>
  </b:bean> 

Property spring.datasource.driver-class-name 属性文件中不需要它,因为您已经直接在 XML 中定义了它:

<b:property name="driverClassName" value="com.mysql.jdbc.Driver" /> 

您可以在 application.properties 中定义的其他属性如下:

spring.datasource.url="jdbc:mysql://5.6.7.8:3306/ab?autoReconnect=true&amp;characterEncoding=utf8"
spring.datasource.username=root
spring.datasource.password=IWin

application.properties 放入 WAR,而不是放入应用服务器的类路径中。

【讨论】:

1) 那么,我根本不需要数据源 bean 吗? 2) 如果我不想在 classpath 中的 application.properties 中未加密密码怎么办? 3)如何识别我的类路径并放置 application.properties ? 1) 我已经扩展了答案。 2)密码在应用服务器的类路径中时更安全,因为只有服务器管理员才能访问它。就像您在应用程序中包含密码一样,您必须在构建应用程序时更早地知道它。这就是为什么更多人可以访问您的密码。 你可以让密码不那么容易阅读。但是请记住,任何有权访问服务器并与您的应用程序具有相同权限的人都将能够以与应用程序相同的方式读取/解密它们。尽管如此,至少让无法访问服务器的人不那么容易阅读密码是有意义的。一种可能的方法是使用 Spring Vault。在此处查看更多详细信息 - projects.spring.io/spring-vault,或在此处 - spring.io/blog/2016/06/24/managing-secrets-with-vault。 至 3):类路径取决于您的应用程序服务器。例如,对于 WebSphere,它是 PROFILE_ROOT/properties,对于 Tomcat,您可以在 catalina.properties 中配置类路径。

以上是关于如何将 OS 环境变量连接到 Spring Web 应用程序项目中 application.properties 中的占位符?的主要内容,如果未能解决你的问题,请参考以下文章

无法将mysql连接到spring boot项目

如何在 Heroku for Node 应用程序上设置环境变量并连接到 PostgreSQL 数据库?

将 WIN / MAC OS 硬盘盒连接到 Ubuntu [关闭]

如何将 spring gcp PubSubTemplate 连接到本地实例?

如何将android设备连接到Spring websocket服务器

如何将 AWS Elasticache Redis 集群连接到 Spring Boot 应用程序?