programing

스프링 부트 application.properties에서 신뢰 저장소 정보 지정

bestprogram 2023. 3. 18. 09:28

스프링 부트 application.properties에서 신뢰 저장소 정보 지정

spring Boot Version 1.2.0을 사용하고 있습니다.해방.Keystore 및 TrustStore를 구성하려고 합니다.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

단, gradle을 통해 트러스트 스토어를 추가할 경우:

bootRun {
    jvmArgs = [ "-Djavax.net.ssl.trustStore=c://foo.jks", "-Djavax.net.ssl.trustStorePassword=password"]
}

잘 작동합니다.

하신 분 요?application.properties★★★★★★★★★★★★★★★★★?

REST 콜이 필요한 경우 다음 방법을 이용하실 수 있습니다.

이것은, 를 개입시킨 발신 콜에 대해서 기능합니다.

RestTemplate콩을 이렇게.

@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);
    }
}

서 ★★★★★http.client.ssl.trust-store ★★★★★★★★★★★★★★★★★」http.client.ssl.trust-store-passwordJKS지정한 신뢰 스토어의 형식과 패스워드를 지정합니다.

은 「」를 .RestTemplateSpring Boot에 부속된 bean을 사용하여 필요한 트러스트 스토어를 사용할 수 있습니다.

Spring Boot, Spring Cloud(마이크로서비스) 및 자기서명 SSL 증명서에 대해서도 같은 문제가 있었습니다.Keystore는 애플리케이션 속성에서 바로 사용할 수 있었지만 Truststore는 그렇지 않았습니다.

application.properties에 keystore와 trustore 설정을 모두 유지하고 시스템에서 truststore 속성을 설정하기 위한 별도의 Configuration bean을 추가했습니다.

@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"));
    }
}

저도 같은 문제가 있는데 좀 더 자세히 설명해 드릴게요.

spring-boot 1.2.2-RELEASE를 사용하고 있으며 Tomcat과 Undertow 모두에서 동일한 결과를 얻었습니다.

application.yml에 다음과 같이 신뢰 스토어를 정의합니다.

server:
  ssl:
    trust-store: path-to-truststore...
    trust-store-password: my-secret-password...

동작하지 않는 한편:

$ java -Djavax.net.debug=ssl -Djavax.net.ssl.trustStore=path-to-truststore... -Djavax.net.ssl.trustStorePassword=my-secret-password... -jar build/libs/*.jar  

완벽하게 잘 작동합니다.

루트 타임의 차이를 확인하는 가장 쉬운 방법은 클라이언트에서 ssl-debug를 netable로 하는 것입니다.작업 시(즉, -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

-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)

...요구를 수행할 때 다음과 같은 예외가 발생합니다.

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

문제를 더 잘 이해하는 데 도움이 되길 바랍니다!

Java 속성 "javax.net.ssl.trustStore" 및 "javax.net.ssl.trustStorePassword"가 스프링 부트 "application.properties"("application.yml")의 "server.ssl.trust-store-password" 및 "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.trustStore-Password"를 설정할 수 없습니다.

"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;
    }

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);

    }     
}

기동 기능 내에서 셋터를 실행할 수 있습니다.

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

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

2018년 10월 3일 편집

설정자를 실행하기 위한 대안으로 "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);

    }
}

응용 프로그램.yml

---
 params: 
   trustStorePath: config/client-truststore.jks
   trustStorePassword: wso2carbon
   keyStorePath: config/wso2carbon.jks
   keyStorePassword: wso2carbon
   defaultType: JKS
---

마지막으로 실행 중인 환경(배포 서버) 내에서 jar 아카이브가 저장된 폴더 아래에 "config"라는 이름의 폴더를 만듭니다.

"config" 폴더 내에 "application.yml", "client-truststore.jks" 및 "wso2carbon.jks." done을 저장합니다.

스프링 부트 2.x.x에 대한 2018-11-27 업데이트

스프링 부트 2.x.x부터는 정적 속성이 지원되지 않게 되었습니다.여기를 참조해 주십시오.저는 개인적으로 이것이 좋은 조치라고 생각하지 않습니다. 왜냐하면 레퍼런스 체인을 따라 복잡한 변경이 이루어져야 하기 때문입니다.

어쨌든, 실장 발췌는, 다음과 같습니다.

'패럴' 계급

    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";  
}

'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);
    }
    
}

Spring Boot과 Embedded Tomcat에서도 같은 문제가 발생했습니다.

이러한 속성은 Tomcat 설정 파라미터만 설정하는 것으로 알고 있습니다.Tomcat 문서에 따르면 이는 클라이언트 인증(즉, 양방향 SSL)에만 사용되며 원격 인증서 확인에는 사용되지 않습니다.

truststore File - 클라이언트 증명서의 검증에 사용하는 신뢰 스토어 파일.

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

HttpClient 의 신뢰 스토어를 설정하려면 , 사용하는HttpClient 의 실장에 의해서 크게 의존합니다.예를 들어 RestTemplate는 기본적으로 스프링부트에서 java.net 등의 표준 J2SE 클래스를 기반으로 SimpleClientHttpRequestFactory를 사용합니다.HttpURL Connection(HttpURL Connection)

Apache HttpClient 문서와 다음 게시물을 기반으로 한 솔루션을 개발했습니다. http://vincentdevillers.blogspot.pt/2013/02/configure-best-spring-resttemplate.html

기본적으로는 설정된 신뢰 스토어의 루트 CA에 의해 서명된 증명서만 신뢰하는 RestTemplate bean이 허용됩니다.

@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;
    }    
}

그리고 필요에 따라 언제든지 이 커스텀 Rest 클라이언트를 사용할 수 있습니다.예를 들어 다음과 같습니다.

@Autowired
private RestTemplate restTemplate;

restTemplate.getForEntity(...)

이것은 Rest 엔드포인트에 접속하려고 하는 것을 전제로 하고 있습니다만, 위의 HttpClient bean을 임의의 용도로 사용할 수도 있습니다.

Spring Boot 응용 프로그램을 Linux 서비스(init.d 스크립트 등)로 실행하는 경우 다음 옵션도 있습니다.your Application.conf라는 이름의 파일을 생성하여 실행 가능한 war/jar 파일 옆에 배치합니다.내용은 비슷해야 합니다.

JAVA_OPTS="
-Djavax.net.ssl.trustStore=path-to-your-trustStore-file
-Djavax.net.ssl.trustStorePassword=yourCrazyPassword
"

댓글은 늦었지만.하지만 저는 이 방법을 사용하여 일을 해왔습니다.여기서 스프링 어플리케이션을 실행할 때 어플리케이션 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());
  }
}

여기 올렉산드르 쉬포타의 대답의 확장판이 있습니다.수입품도 포함해서요.패키지org.apache.http.*에 기재되어 있습니다.변경사항에 대해 설명하겠습니다.

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Value("${http.client.ssl.key-store}")
private Resource keyStore;

@Value("${http.client.ssl.trust-store}")
private Resource trustStore;

// I use the same pw for both keystores:
@Value("${http.client.ssl.trust-store-password}")
private String keyStorePassword;

// wasn't able to provide this as a @Bean...:
private RestTemplate getRestTemplate() {
  try {
    SSLContext sslContext = SSLContexts.custom()
        // keystore wasn't within the question's scope, yet it might be handy:
        .loadKeyMaterial(
            keyStore.getFile(),
            keyStorePassword.toCharArray(),
            keyStorePassword.toCharArray())
        .loadTrustMaterial(
            trustStore.getURL(),
            keyStorePassword.toCharArray(),
            // use this for self-signed certificates only:
            new TrustSelfSignedStrategy())
        .build();

    HttpClient httpClient = HttpClients.custom()
        // use NoopHostnameVerifier with caution, see https://stackoverflow.com/a/22901289/3890673
        .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()))
        .build();

    return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
  } catch (IOException | GeneralSecurityException e) {
    throw new RuntimeException(e);
  }
}

봄에는 필요한 속성만 추가하면 전체 JVM에서 사용할 수 있습니다.

javax:
  net:
    ssl:
      key-store-password: ${KEYSTORE_SECRET}
      key-store-type: PKCS12
      trust-store-password: ${TRUSTSTORE_SECRET}
      trust-store-type: PKCS12

마이크로 서비스 인프라스트럭처(문제와 맞지 않음)에서는 다음 항목을 사용하지 마십시오.

server:
  ssl:
    trust-store: path-to-truststore...
    trust-store-password: my-secret-password...

대신 리본 로드밸런서를 설정할 수 있습니다.

ribbon: 
  TrustStore: keystore.jks
  TrustStorePassword : example
  ReadTimeout: 60000
  IsSecure: true
  MaxAutoRetries: 1

여기 https://github.com/rajaramkushwaha/https-zuul-proxy-spring-boot-app에서 작업 샘플을 찾을 수 있습니다.그것에 대해서도 시시콜콜한 논의가 있었지만, 나는 그것을 찾을 수 없었다.

언급URL : https://stackoverflow.com/questions/27724544/specifying-trust-store-information-in-spring-boot-application-properties