我应该在 Spring 引导项目的什么地方存储开发凭据?

Where should I store development credentials on a Spring Boot project?

我应该将开发凭据存储在 Spring 启动项目的什么位置,这样它们就不会提交到存储库?最标准的方式是什么?

在其他框架(Rails、Clojure)中,我习惯于拥有一个文件,但我不会将其提交给该信息所在的存储库。类似于辅助 application.properties 的东西被合并并且永远不会提交。有这种东西吗?

我正在部署到 Heroku,它在 Spring 可以获取的环境变量中提供凭据,因此,该部分已解决。如果我部署在其他地方,它将是一个类似的配置。

Spring Boot Docs, chapter 24, Externalized Configuration 中,有一个所有定义属性的地方的列表。我浏览了该列表,试图找到适当的凭据位置,但找不到:

Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).

这不是 devtools 的东西,因为你可能想在本地开发禁用 devloots。

@TestPropertySource annotations on your tests.

这与测试无关

@SpringBootTest#properties annotation attribute on your tests.

再说一次,不是测试。

Command line arguments.

我不想在命令行中使用凭据,因为这些凭据往往在计算机中 public,因此,另一个程序可以获取它们。但除此之外,我在开发时不会 运行ning 命令;我正在从 IntelliJ 触发应用程序。

Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)

与下面的环境 variable/system 属性相同。

ServletConfig init parameters. ServletContext init parameters. JNDI attributes from java:comp/env.

开发本地生成 jar 时,这些似乎根本不适用,

Java System properties (System.getProperties()).

我不确定设置它们的合适方法是什么,但感觉很费力。

OS environment variables.

我要么将它们设置在我的 OS 上,这对新开发人员来说是不透明的,要么我将它们设置在 IntelliJ 运行 配置文件中,这使它们成为存储库的一部分,这就是我我正在努力避免。

A RandomValuePropertySource that only has properties in random.*.

它们不是随机的。

Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)

这可能是,但我不确定该文件应该存放在哪里。

Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)

我希望能够将配置文件特定的应用程序属性提交到存储库,因此,我无法在这些文件中存储凭据。

Application properties outside of your packaged jar (application.properties and YAML variants).

这可能是,但我不确定该文件应该存放在哪里。

Application properties packaged inside your jar (application.properties and YAML variants).

我想提交那个文件,所以我不能在那里存储凭据。

@PropertySource annotations on your @Configuration classes. Default properties (specified using SpringApplication.setDefaultProperties).

使用类似的东西,我可以制作自己的东西,从未提交的文件中选择属性,但我有兴趣遵循 Spring Boot 的最佳和常见做法,而不是自己制作;特别是因为我才刚刚开始。

这取决于您的配置。由于 Spring 的 Environment 抽象,您可以在运行时从环境中覆盖属性,因此根据您的部署,有很多方法可以做到这一点。但是,请注意,虚假的安全感可能是真正的颈椎病。您希望将配置维护为代码 - 可以对其进行版本控制、审查和审计,而不是将其作为某人 PC 上用于注入随机运行时变量的文本文件。这是 classic "works on my machine" 问题。

你没有说任何关于你的部署的事,所以几乎不可能说;如果您使用 Tomcat,则可以使用 setenv.sh。就目前而言,您的问题很模糊;我会在您更新 post.

时更新我的​​答案

编辑,根据 OP 在评论中所说:

您可以只提供键值对作为 JVM 变量。例如,如果使用 Gradle 构建,您可以执行 gradle clean bootRun -Dmy.secret.key=whatever,并且在 build.gradle:

bootRun {
  systemProperties = System.properties
}

您还可以保留未提交给 Git 的 application-local.properties,并使用 -Dspring.profiles.active=default,local 配置文件启动应用程序,在这种情况下 Spring 将合并 application.propertiesapplication-local.properties,后者的优先级更高。就像我之前说的,这是一个非常糟糕的想法,但你是一个自由人,所以...

Spring Boot 本身没有对加密属性的 first-class 支持,但如果你愿意自己做,你可以提交所有内容,然后启动应用程序传递密钥,或以某种方式在您的构建环境中管理它(如 Maven settings.xml 中的 属性)。

编辑 2,如何在运行时使用环境变量覆盖 application.properties 中的属性:

my.secret.key=${MY_SECRET_KEY:default}

如果环境变量 MY_SECRET_KEY 存在,my.secret.key 将等于它的值;否则它将等于 default.

Spring-boot 允许你在不同的地方外化你的配置。对于所讨论的场景,可以在 ${PROJECT_ROOT}/config/ 下放置一个 application.properties 文件。 这些属性将覆盖任何其他已定义的属性。 在这种情况下,它没有打包在可部署的工件中。
查看 Application property files 了解更多详情。

config/application.properties.example 下提供示例配置文件作为一个很好的起点。该文件可以进行版本控制。 为避免无意的提交,请忽略其他所有内容。

使用 git,忽略文件可以包含以下片段(忽略除以 .exampleREADME.md 结尾的文件以外的所有内容):

.gitignore:

/config/*
!/config/README.md
!/config/*.example