在spring boot application.properties中指定信任库信息

use*_*912 49 ssl properties truststore spring-boot

我使用的是springBootVersion 1.2.0.RELEASE.我正在尝试通过配置我的密钥库和信任库application.properties.

当我添加以下设置时,我可以让密钥库工作,但不能使用信任库.

server.ssl.key-store=classpath:foo.jks
server.ssl.key-store-password=password
server.ssl.key-password=password
server.ssl.trust-store=classpath:foo.jks
server.ssl.trust-store-password=password
Run Code Online (Sandbox Code Playgroud)

但是,如果我通过gradle添加信任库:

bootRun {
    jvmArgs = [ "-Djavax.net.ssl.trustStore=c://foo.jks", "-Djavax.net.ssl.trustStorePassword=password"]
}
Run Code Online (Sandbox Code Playgroud)

它工作得很好.

有没有人用过application.properties信托商店?

Sas*_*ota 28

如果您需要进行REST调用,可以使用下一种方法.

这将适用于拨打电话RestTemplate.

RestTemplate像这样声明bean.

@Configuration
public class SslConfiguration {
    @Value("${http.client.ssl.trust-store}")
    private Resource keyStore;
    @Value("${http.client.ssl.trust-store-password}")
    private String keyStorePassword;

    @Bean
    RestTemplate restTemplate() throws Exception {
        SSLContext sslContext = new SSLContextBuilder()
                .loadTrustMaterial(
                        keyStore.getURL(),
                        keyStorePassword.toCharArray()
                ).build();
        SSLConnectionSocketFactory socketFactory = 
                new SSLConnectionSocketFactory(sslContext);
        HttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(socketFactory).build();
        HttpComponentsClientHttpRequestFactory factory = 
                new HttpComponentsClientHttpRequestFactory(httpClient);
        return new RestTemplate(factory);
    }
}
Run Code Online (Sandbox Code Playgroud)

where http.client.ssl.trust-storehttp.client.ssl.trust-store-password指向信任库的JKS格式和指定信任库的密码.

这将覆盖RestTemplateSpring Boot提供的bean,并使其使用您需要的信任存储.

  • @OleksandrShpota这是"资源"类型的全名?我要把哪个班级导入班级? (6认同)
  • @ riccardo.cardin`org.springframework.core.io.Resource`. (5认同)
  • `http.client.ssl.trust-store` 和 `http.client.ssl.trust-store-password` 是自定义属性,不是吗? (2认同)

Mat*_*vić 14

我在Spring Boot,Spring Cloud(微服务)和自签名SSL证书方面遇到了同样的问题.Keystore从应用程序属性开箱即用,而Truststore则没有.

我最终在application.properties中保留了密钥库和可信任配置,并添加了一个单独的配置bean,用于使用System配置信任库属性.

@Configuration
public class SSLConfig {
    @Autowired
    private Environment env;

    @PostConstruct
    private void configureSSL() {
      //set to TLSv1.1 or TLSv1.2
      System.setProperty("https.protocols", "TLSv1.1");

      //load the 'javax.net.ssl.trustStore' and
      //'javax.net.ssl.trustStorePassword' from application.properties
      System.setProperty("javax.net.ssl.trustStore", env.getProperty("server.ssl.trust-store")); 
      System.setProperty("javax.net.ssl.trustStorePassword",env.getProperty("server.ssl.trust-store-password"));
    }
}
Run Code Online (Sandbox Code Playgroud)


Mag*_*son 13

我有同样的问题,我会尝试更详细地解释一下.

我正在使用spring-boot 1.2.2-RELEASE并在Tomcat和Undertow上尝试使用相同的结果.

在application.yml中定义信任存储,如:

server:
  ssl:
    trust-store: path-to-truststore...
    trust-store-password: my-secret-password...
Run Code Online (Sandbox Code Playgroud)

不起作用,而:

$ java -Djavax.net.debug=ssl -Djavax.net.ssl.trustStore=path-to-truststore... -Djavax.net.ssl.trustStorePassword=my-secret-password... -jar build/libs/*.jar  
Run Code Online (Sandbox Code Playgroud)

工作得非常好.

在rutime中查看差异的最简单方法是在客户端启用ssl-debug.工作时(即使用-D标志)将类似以下内容写入控制台(在处理第一个请求期间):

trustStore is: path-to-truststore...
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
  Subject: C=..., ST=..., O=..., OU=..., CN=...
  Issuer:  C=..., ST=..., O=..., OU=..., CN=...
  Algorithm: RSA; Serial number: 0x4d2
  Valid from Wed Oct 16 17:58:35 CEST 2013 until Tue Oct 11 17:58:35 CEST 2033
Run Code Online (Sandbox Code Playgroud)

没有-D标志我得到:

trustStore is: /Library/Java/JavaVirtualMachines/jdk1.8.0_11.jdk/Contents/Home/jre/lib/security/cacerts
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert: ... (one for each CA-cert in the defult truststore)
Run Code Online (Sandbox Code Playgroud)

...当执行请求时,我得到了异常:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Run Code Online (Sandbox Code Playgroud)

希望有助于更好地理解这个问题!

  • !!!请阅读!!!非常重要的精度:您必须在jar之前传递信任库,否则,Spring上下文将接管并且您将继续获得相同的错误. (9认同)
  • 有人知道为什么“application.yml”方式不起作用吗? (6认同)
  • 参见命令行:`$ java -Djavax.net.ssl.trustStore=path-to-truststore -jar blabla.jar`,trust store位于jar之前。如果您在信任存储之前传递 jar,它将无法工作。我猜想,Spring 有一种覆盖和锁定上下文的机制。 (2认同)
  • @avi.elkharrat,感谢您指出这一点。由于这个事实,我已经浪费了很多时间。事实证明,除了我之外,没有人可以责怪;**他们在手册中非常清楚地指出了**:`java [options] -jar <jarfile> [args...]`。`-jar <jarfile>` 之后的所有内容最终都在应用程序中,而不是在 Java 本身中...... (2认同)

jpt*_*jpt 7

我也遇到了与Spring Boot和嵌入式Tomcat相同的问题.

据我所知,这些属性只设置Tomcat配置参数.根据Tomcat文档,这仅用于客户端身份验证(即用于双向SSL),而不用于验证远程证书:

truststoreFile - 用于验证客户端证书的信任库文件.

https://tomcat.apache.org/tomcat-8.0-doc/config/http.html

为了配置HttpClient的信任库,它在很大程度上取决于您使用的HttpClient实现.例如,对于RestTemplate,默认情况下,Spring Boot使用基于标准J2SE类的SimpleClientHttpRequestFactory,如java.net.HttpURLConnection.

我想出了一个基于Apache HttpClient文档和这些帖子的解决方案:http : //vincentdevillers.blogspot.pt/2013/02/configure-best-spring-resttemplate.html http://literatejava.com/networks /忽略的SSL证书,错误的Apache-HttpClient的-4-4 /

基本上,这允许RestTemplate bean仅信任由配置的信任库中的根CA签名的证书.

@Configuration
public class RestClientConfig {

    // e.g. Add http.client.ssl.trust-store=classpath:ssl/truststore.jks to application.properties
    @Value("${http.client.ssl.trust-store}")
    private Resource trustStore;

    @Value("${http.client.ssl.trust-store-password}")
    private char[] trustStorePassword;

    @Value("${http.client.maxPoolSize}")
    private Integer maxPoolSize;


    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

    @Bean
    public HttpClient httpClient() {

        // Trust own CA and all child certs
        Registry<ConnectionSocketFactory> socketFactoryRegistry = null;
        try {
            SSLContext sslContext = SSLContexts
                    .custom()
                    .loadTrustMaterial(trustStore.getFile(),
                            trustStorePassword)
                    .build();

            // Since only our own certs are trusted, hostname verification is probably safe to bypass
            SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
                    new HostnameVerifier() {

                        @Override
                        public boolean verify(final String hostname,
                                final SSLSession session) {
                            return true;
                        }
            });

            socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", sslSocketFactory)
                    .build();           

        } catch (Exception e) {
            //TODO: handle exceptions
            e.printStackTrace();
        }

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connectionManager.setMaxTotal(maxPoolSize);
        // This client is for internal connections so only one route is expected
        connectionManager.setDefaultMaxPerRoute(maxPoolSize);
        return HttpClientBuilder.create()
                .setConnectionManager(connectionManager)
                .disableCookieManagement()
                .disableAuthCaching()
                .build();
    }

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(httpRequestFactory());
        return restTemplate;
    }    
}
Run Code Online (Sandbox Code Playgroud)

然后您可以在需要时使用此自定义Rest客户端,例如:

@Autowired
private RestTemplate restTemplate;

restTemplate.getForEntity(...)
Run Code Online (Sandbox Code Playgroud)

这假设您尝试连接到Rest端点,但您也可以使用上面的HttpClient bean来实现您想要的任何内容.

  • 我赞成这一点,因为我整理了一小段代码来演示和证明 `server.ssl.trust-store` 用于双向 TLS(如果设置了 `server.ssl.client-auth`,则不会产生任何影响)用于传出连接。答案可以被接受为 stackoverflow 答案。我还想在这里说明文档足够了:https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html (2认同)

Geo*_*ang 6

Java属性“ javax.net.ssl.trustStore”和“ javax.net.ssl.trustStorePassword”不对应于“ Spring boot”中的“ server.ssl.trust-store”和“ server.ssl.trust-store-password” application.properties”(“ application.yml”)

因此,您不能仅通过在“服务器”中设置“ server.ssl.trust-store”和“ server.ssl.trust-store-password”来设置“ javax.net.ssl.trustStore”和“ javax.net.ssl.trustStorePassword” application.properties”(“ application.yml”)

通过Spring Boot 外部化配置来设置“ javax.net.ssl.trustStore”和“ javax.net.ssl.trustStorePassword”

以下是我的实现摘录:

Params类保存外部设置

@Component
@ConfigurationProperties("params")
public class Params{

    //default values, can be override by external settings
    public static String trustStorePath = "config/client-truststore.jks";
    public static String trustStorePassword = "wso2carbon";
    public static String keyStorePath = "config/wso2carbon.jks";
    public static String keyStorePassword = "wso2carbon";
    public static String defaultType = "JKS";

    public void setTrustStorePath(String trustStorePath){
        Params.trustStorePath = trustStorePath;
    }

    public void settrustStorePassword(String trustStorePassword){
        Params.trustStorePassword=trustStorePassword;
    }

    public void setKeyStorePath(String keyStorePath){
        Params.keyStorePath = keyStorePath;
    }

    public void setkeyStorePassword(String keyStorePassword){
        Params.keyStorePassword = keyStorePassword;
    }

    public void setDefaultType(String defaultType){
        Params.defaultType = defaultType;
    }
Run Code Online (Sandbox Code Playgroud)

KeyStoreUtil类承担“ javax.net.ssl.trustStore”和“ javax.net.ssl.trustStorePassword”的设置

public class KeyStoreUtil {

    public static void setTrustStoreParams() {
        File filePath = new File( Params.trustStorePath);
        String tsp = filePath.getAbsolutePath();
        System.setProperty("javax.net.ssl.trustStore", tsp);
        System.setProperty("javax.net.ssl.trustStorePassword", Params.trustStorePassword);
        System.setProperty("javax.net.ssl.keyStoreType", Params.defaultType);

    }

    public static void setKeyStoreParams() {
        File filePath = new File(Params.keyStorePath);
        String ksp = filePath.getAbsolutePath();
        System.setProperty("Security.KeyStore.Location", ksp);
        System.setProperty("Security.KeyStore.Password", Params.keyStorePassword);

    }     
}
Run Code Online (Sandbox Code Playgroud)

您可以在启动函数中执行设置器

@SpringBootApplication
@ComponentScan("com.myapp.profiles")
public class ProfilesApplication {

    public static void main(String[] args) {
        KeyStoreUtil.setKeyStoreParams();
        KeyStoreUtil.setTrustStoreParams();
        SpringApplication.run(ProfilesApplication.class, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

于2018-10-03编辑

您可能还希望采用注释“ PostConstruct”作为执行设置程序的替代方法

import javax.annotation.PostConstruct;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackages={"com.xxx"})
public class GateApplication {

    public static void main(String[] args) {
        SpringApplication.run(GateApplication.class, args);
    }

    @PostConstruct
    void postConstruct(){
        setTrustStoreParams();
        setKeyStoreParams();
    }


    private static void setTrustStoreParams() {
        File filePath = new File( Params.trustStorePath);
        String tsp = filePath.getAbsolutePath();
        System.setProperty("javax.net.ssl.trustStore", tsp);
        System.setProperty("javax.net.ssl.trustStorePassword", Params.trustStorePassword);
        System.setProperty("javax.net.ssl.keyStoreType", Params.defaultType);

    }

    private static void setKeyStoreParams() {
        File filePath = new File(Params.keyStorePath);
        String ksp = filePath.getAbsolutePath();
        System.setProperty("Security.KeyStore.Location", ksp);
        System.setProperty("Security.KeyStore.Password", Params.keyStorePassword);

    }
}
Run Code Online (Sandbox Code Playgroud)

application.yml

---
 params: 
   trustStorePath: config/client-truststore.jks
   trustStorePassword: wso2carbon
   keyStorePath: config/wso2carbon.jks
   keyStorePassword: wso2carbon
   defaultType: JKS
---
Run Code Online (Sandbox Code Playgroud)

最后,在运行环境(部署服务器)中,在存储jar存档的同一文件夹下创建一个名为“ config”的文件夹。

在“ config”文件夹中,存储“ application.yml”,“ client-truststore.jks”和“ wso2carbon.jks”。完成了!

关于Spring Boot 2.xx的更新于2018-11-27

从Spring Boot 2.xx开始,不再支持静态属性,请参见此处。我个人认为这不是一个好举动,因为必须沿着参考链进行复杂的更改...

无论如何,摘录摘录可能看起来像这样

“ Params”类

    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;

    import lombok.Data;

    /**
     * Params class represent all config parameters that can 
     * be external set by spring xml file
     */

    @Component
    @ConfigurationProperties("params")
    @Data
    public class Params{

        //default values, can be override by external settings
        public String trustStorePath = "config/client-truststore.jks";
        public String trustStorePassword = "wso2carbon";
        public String keyStorePath = "config/wso2carbon.jks";
        public String keyStorePassword = "wso2carbon";
        public String defaultType = "JKS";  
}
Run Code Online (Sandbox Code Playgroud)

“ Springboot应用程序类”(带有“ PostConstruct”)

import java.io.File;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackages={"com.xx.xx"})
public class BillingApplication {

    @Autowired
    Params params;

    public static void main(String[] args) {
        SpringApplication.run(BillingApplication.class, args);
    }

    @PostConstruct
    void postConstruct() {

        // set TrustStoreParams
        File trustStoreFilePath = new File(params.trustStorePath);
        String tsp = trustStoreFilePath.getAbsolutePath();
        System.setProperty("javax.net.ssl.trustStore", tsp);
        System.setProperty("javax.net.ssl.trustStorePassword", params.trustStorePassword);
        System.setProperty("javax.net.ssl.keyStoreType", params.defaultType);
        // set KeyStoreParams
        File keyStoreFilePath = new File(params.keyStorePath);
        String ksp = keyStoreFilePath.getAbsolutePath();
        System.setProperty("Security.KeyStore.Location", ksp);
        System.setProperty("Security.KeyStore.Password", params.keyStorePassword);
    }

}
Run Code Online (Sandbox Code Playgroud)


小智 5

虽然我评论晚了。但我已经使用这种方法来完成这项工作。在这里,当我运行我的 spring 应用程序时,我通过它提供应用程序 yaml 文件,-Dspring.config.location=file:/location-to-file/config-server-vault-application.yml其中包含我的所有属性

config-server-vault-application.yml
***********************************
server:
  port: 8888
  ssl:
    trust-store: /trust-store/config-server-trust-store.jks
    trust-store-password: config-server
    trust-store-type: pkcs12

************************************
Java Code
************************************
@SpringBootApplication
public class ConfigServerApplication {

 public static void main(String[] args) throws IOException {
    setUpTrustStoreForApplication();
    SpringApplication.run(ConfigServerApplication.class, args);
 }

 private static void setUpTrustStoreForApplication() throws IOException {
    YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
    List<PropertySource<?>> applicationYamlPropertySource = loader.load(
            "config-application-properties", new UrlResource(System.getProperty("spring.config.location")));
    Map<String, Object> source = ((MapPropertySource) applicationYamlPropertySource.get(0)).getSource();
    System.setProperty("javax.net.ssl.trustStore", source.get("server.ssl.trust-store").toString());
    System.setProperty("javax.net.ssl.trustStorePassword", source.get("server.ssl.trust-store-password").toString());
  }
}
Run Code Online (Sandbox Code Playgroud)