【问题标题】:Spring Boot how to hide passwords in properties fileSpring Boot如何在属性文件中隐藏密码
【发布时间】:2016-09-21 03:26:33
【问题描述】:

Spring Boot 使用属性文件,至少默认情况下,密码是纯文本的。是否有可能以某种方式隐藏/解密这些?

【问题讨论】:

    标签: java spring spring-boot


    【解决方案1】:

    Spring Cloud Config Server 将允许这种类型的行为。使用 JCE,您可以在服务器上设置一个密钥并使用它来加密应用程序属性。

    http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html

    【讨论】:

      【解决方案2】:

      更新:我注意到人们对此投了反对票,所以我不得不说,虽然这不是一个理想的解决方案,但在某些用例中这是可行的并且可以接受。 当服务绑定到应用程序时,Cloudfoundry 使用环境变量注入凭据。更多信息https://docs.cloudfoundry.org/devguide/services/application-binding.html

      如果你的系统不是共享的,那么对于本地开发来说这也是可以接受的。当然,更安全可靠的方式在@J-Alex 的Answer 中进行了说明。

      答案:

      如果您想隐藏您的密码,那么最简单的解决方案是在application.properties 文件中或直接在您的代码中使用环境变量

      application.properties:

      mypassword=${password}
      

      然后在你的配置类中:

      @Autowired
      private Environment environment;
      
      [...]//Inside a method
      System.out.println(environment.getProperty("mypassword"));
      

      在您的configuration 班级中:

      @Value("${password}")
      private String herokuPath;
      
      [...]//Inside a method
      System.out.println(herokuPath);
      

      注意:设置环境变量后可能需要重新启动。 对于窗户:

      请参阅此Documentation 了解更多信息。

      【讨论】:

      • 我认为在环境变量中设置主密码不是一个好主意。密码现在比必要的更暴露。与在环境中设置它相比,为它提供一个如 Federico 所示的初创公司更少暴露且更“安全”。
      • 是的,如果您使用的是共享计算机,则不会。但是,如果您是计算机的唯一管理员,则其他用户无法看到环境变量。我回答了隐藏的部分和更容易的部分。但是,是的,我同意 Federico 建议的方法要好得多。
      • @Jaavaaan 在环境变量中提供 JASYPT_ENCRYPTOR_PASSWORD 以解码数据库密码与此答案同样不安全。
      • @Jaavaaan 请阅读更新。我已经提到这在所有情况下都不是安全的,但是有像 CF 这样的有效用例。还指出了使用 HashiCorp Vault 的更好的高度安全的解决方案。
      【解决方案3】:

      您可以使用 Jasypt 来加密属性,因此您可以拥有这样的属性:

      db.password=ENC(XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx+hNPrJyQT88=)
      

      Jasypt 允许您使用不同的算法加密您的属性,一旦您获得了放入 ENC(...) 中的加密属性。例如,您可以使用终端通过 Jasypt 以这种方式加密:

      encrypted-pwd$ java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar  org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="contactspassword" password=supersecretz algorithm=PBEWithMD5AndDES
      
      ----ENVIRONMENT-----------------
      
      Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 24.45-b08
      
      
      
      ----ARGUMENTS-------------------
      
      algorithm: PBEWithMD5AndDES
      input: contactspassword
      password: supersecretz
      
      
      
      ----OUTPUT----------------------
      
      XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx+hNPrJyQT88=
      

      要使用 Spring Boot 轻松配置它,您可以使用其启动器 jasypt-spring-boot-starter 和组 ID com.github.ulisesbocchio

      请记住,您需要使用与加密属性相同的密码来启动您的应用程序。所以,你可以这样启动你的应用:

      mvn -Djasypt.encryptor.password=supersecretz spring-boot:run
      

      或者使用环境变量(感谢 spring boot 宽松绑定):

      export JASYPT_ENCRYPTOR_PASSWORD=supersecretz
      mvn spring-boot:run
      

      您可以查看以下链接了解更多详情:

      https://www.ricston.com/blog/encrypting-properties-in-spring-boot-with-jasypt-spring-boot/

      要在您的应用程序中使用您的加密属性,只需像往常一样使用它,使用您喜欢的任何一种方法(Spring Boot 具有魔力,无论如何属性当然必须在类路径中):

      使用@Value注解

      @Value("${db.password}")
      private String password;
      

      或者使用Environment

      @Autowired
      private Environment environment;
      
      public void doSomething(Environment env) {
          System.out.println(env.getProperty("db.password"));
      }
      

      更新:对于生产环境,为了避免在命令行中暴露密码,因为您可以使用ps查询进程,使用history等查询之前的命令。您可以:

      • 创建这样的脚本:touch setEnv.sh
      • 编辑setEnv.sh 以导出JASYPT_ENCRYPTOR_PASSWORD 变量

        #!/bin/bash

        导出 JASYPT_ENCRYPTOR_PASSWORD=supersecretz

      • . setEnv.sh执行文件
      • 使用mvn spring-boot:run & 在后台运行应用程序
      • 删除文件setEnv.sh
      • 取消设置之前的环境变量:unset JASYPT_ENCRYPTOR_PASSWORD

      【讨论】:

      • 能否请您使用 gradle @Ferica Piazza 详细解释一下
      • @FedericoPiazza mvn -Djasypt.encryptor.password=supersecretz spring-boot:run 不会出现在ps 输出中,暴露密码吗?
      • @SrkiRakic 是的,当然。这仅用于开发,如果您希望将其用于生产,则应使用环境变量。 Spring boot 允许你使用JASYPT_ENCRYPTOR_PASSWORD
      • 哈哈,它是如何进入环境变量的?可能来自另一个文件,例如服务定义:D jasypt 在密码派生方面也已过时,因此请确保使用完全随机的 32 个字符的密码
      • @ChrisF 我认为您误解了加密的工作原理。 input="this is the text I want to encrypt"password="this is the key used to encrypt the input"
      【解决方案4】:

      对于已经提出的解决方案,我可以添加一个选项来配置外部Secrets Manager,例如Vault

      1. 配置 Vault Server vault server -dev仅适用于 DEV,不适用于 PROD
      2. 写秘密vault write secret/somename key1=value1 key2=value2
      3. 验证秘密vault read secret/somename

      将以下依赖项添加到您的 SpringBoot 项目中:

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-vault-config</artifactId>
      </dependency>
      

      添加保险柜配置属性:

      spring.cloud.vault.host=localhost
      spring.cloud.vault.port=8200
      spring.cloud.vault.scheme=http
      spring.cloud.vault.authentication=token
      spring.cloud.vault.token=${VAULT_TOKEN}
      

      VAULT_TOKEN 作为环境变量传递。

      参考文档here.

      有一个Spring Vault 项目也可用于访问、存储和撤销机密。

      依赖:

      <dependency>
          <groupId>org.springframework.vault</groupId>
          <artifactId>spring-vault-core</artifactId>
      </dependency>
      

      配置 Vault 模板:

      @Configuration
      class VaultConfiguration extends AbstractVaultConfiguration {
      
        @Override
        public VaultEndpoint vaultEndpoint() {
          return new VaultEndpoint();
        }
      
        @Override
        public ClientAuthentication clientAuthentication() {
          return new TokenAuthentication("…");
        }
      }
      

      注入和使用VaultTemplate:

      public class Example {
      
        @Autowired
        private VaultOperations operations;
      
        public void writeSecrets(String userId, String password) {
            Map<String, String> data = new HashMap<String, String>();
            data.put("password", password);
            operations.write(userId, data);
        }
      
        public Person readSecrets(String userId) {
            VaultResponseSupport<Person> response = operations.read(userId, Person.class);
            return response.getBody();
        }
      }
      

      使用保险柜PropertySource

      @VaultPropertySource(value = "aws/creds/s3",
        propertyNamePrefix = "aws."
        renewal = Renewal.RENEW)
      public class Config {
      
      }
      

      使用示例:

      public class S3Client {
      
        // inject the actual values
        @Value("${aws.access_key}")
        private String awsAccessKey;
        @Value("${aws.secret_key}")
        private String awsSecretKey;
      
        public InputStream getFileFromS3(String filenname) {
          // …
        }
      }
      

      【讨论】:

      • 这个解决方案+1。使用像 vault / etcd(或任何其他)这样的系统是要走的路。 diogomonica.com/2017/03/27/…
      • -1 因为这并不能解释如何保护“主”密钥 (VAULT_TOKEN)。 VAULT_TOKEN 环境变量从何而来?它是如何保护的?在不保护该密钥的情况下,攻击者可以使用它使用 Spring Boot jar 中打包的代码从保管库中检索秘密。
      • 保护 prod 也是主要问题。所以,这里不得不说。开发/质量保证环境指南(如果可以的话)。
      • 这在有很多密码时有效。它适用于一个密码进行连接,但将保险库密码放入环境中很有趣,因此您不必将另一个密码放入同一环境中。
      • 为什么我们只想用于开发?产品很重要。
      【解决方案5】:

      如果您在 Spring Boot 环境中使用非常流行的 Kubernetes (K8S) 或 OpenShift,则可以在运行时存储和检索应用程序属性。这种技术称为秘密。在 Kubernetes 或 OpenShift 的配置 yaml 文件中,您为其声明变量和占位符,并在 K8S\OpenShift 端声明与此占位符对应的实际值。 实现细节见: K8S:https://kubernetes.io/docs/concepts/configuration/secret/ OpenShift:https://docs.openshift.com/container-platform/3.11/dev_guide/secrets.html

      【讨论】:

        【解决方案6】:

        我在 Spring Boot App 的 application.properties 中隐藏 DB-Password 的解决方案确实实现了 here

        场景:一些假密码已经在启动时从application.properties 读取并保存,在全局 Spring 对象 ConfigurableEnvironment 中,将在运行时以编程方式替换为真正的 DB-Password。 真正的密码将从另一个配置文件中读取,保存在安全的项目外部位置。

        不要忘记:从main class 调用Bean 使用:

        @Autowired
        private SchedUtilility utl;
        

        【讨论】:

          【解决方案7】:

          除了流行的 K8s、jasypt 或 vault 解决方案之外,还有Karmahostage。它使您能够:

          @EncryptedValue("${application.secret}")
          private String application;
          

          它的工作方式与 jasypt 相同,但加密发生在专用 saas 解决方案上,并附加了更细粒度的 ACL 模型。

          【讨论】:

            猜你喜欢
            • 2017-09-25
            • 2020-01-27
            • 2018-12-13
            • 2015-10-26
            • 1970-01-01
            • 1970-01-01
            • 2011-05-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多