์ด๋ฒ ํฌ์คํธ์์๋ Spring Boot ์ ํ๋ฆฌ์ผ์ด์
์์ TLS 1.3์ ์ฌ์ฉํ์ฌ ์์ ํ HTTPS ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ์ค๋ช
ํฉ๋๋ค. ์ด๋ฅผ ์ํด Apache HttpComponents ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ RestTemplate
์ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ฃน๋๋ค
1. TLS๋?
TLS(Transport Layer Security)๋ ๋คํธ์ํฌ ํต์ ์ ์ํธํํ์ฌ ๋ณด์์ ์ ๊ณตํ๋ ํ๋กํ ์ฝ์ ๋๋ค. TLS๋ ๋ฐ์ดํฐ์ ๊ธฐ๋ฐ์ฑ๊ณผ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๋ฉฐ, ์์ ํ ํต์ ์ ์ํด HTTPS์์ ์ฌ์ฉ๋ฉ๋๋ค.
2. ์ TLS 1.3์ ์ฌ์ฉํ๋๊ฐ?
TLS 1.3์ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋ณด์ ๊ฐํ: TLS 1.3์ ์ด์ ๋ฒ์ ๋ณด๋ค ํฅ์๋ ์ํธํ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋ณด์ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ ๋ณด์์ ๊ฐํํฉ๋๋ค.
- ์ฑ๋ฅ ํฅ์: ํธ๋์ ฐ์ดํฌ ๊ณผ์ ์ด ๋จ์ํ๋์ด ์ฐ๊ฒฐ ์ค์ ์๊ฐ์ด ๋จ์ถ๋๊ณ ์ฑ๋ฅ์ด ํฅ์๋ฉ๋๋ค.
- ํธํ์ฑ: ์ต์ ๋ธ๋ผ์ฐ์ ์ ํด๋ผ์ด์ธํธ๋ TLS 1.3์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ๋ฉฐ, ์ด๋ฅผ ํตํด ํธํ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
3. Gradle ์์กด์ฑ ์ถ๊ฐ
Spring Boot์์ TLS 1.3์ ์ง์ํ๋ RestTemplate
์ ์ค์ ํ๊ธฐ ์ํด ํ์ํ Apache HttpComponents ์์กด์ฑ์ build.gradle
ํ์ผ์ ์ถ๊ฐํฉ๋๋ค:
์ ๋ ๊ฐ์ฅ ์ต์ ๋ฒ์ ์ธ 5.4-alpha2 5.3-alpha2 ๋ฅผ ์ฐพ์์ ์ค์ ํ์ต๋๋ค.
dependencies {
// ๊ธฐํ ์ข
์์ฑ
// Apache HttpComponents dependencies
implementation group: 'org.apache.httpcomponents.client5', name: 'httpclient5', version: '5.4-alpha2'
implementation group: 'org.apache.httpcomponents.core5', name: 'httpcore5', version: '5.3-alpha2'
}
4. RestTemplateConfig ํด๋์ค ์์ฑ
RestTemplate
์ TLS 1.3์ ์ฌ์ฉํ๋๋ก ์ค์ ํ๊ธฐ ์ํด RestTemplateConfig
ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค. ์ต์ ๋ฒ์ ์ Apache HttpComponents ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ SSL ์ปจํ
์คํธ์ ์ฐ๊ฒฐ ํ์ ๊ตฌ์ฑํฉ๋๋ค.
RestTemplateConfig.java
package enha.eodilo.config;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.ssl.TLS;
import org.apache.hc.core5.util.Timeout;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.KeyStoreException;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(null, (chain, authType) -> true) // ๋ชจ๋ ์ธ์ฆ์๋ฅผ ์ ๋ขฐํ๋๋ก ์ค์
.build();
DefaultClientTlsStrategy tlsStrategy = new DefaultClientTlsStrategy(sslContext);
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
.setTlsStrategy(tlsStrategy)
.setDefaultTlsConfig(tlsConfig -> tlsConfig
.setHandshakeTimeout(Timeout.ofSeconds(30)) // ํธ๋์
ฐ์ดํฌ 30์ด ์ ํ
.setSupportedProtocols(TLS.V_1_3)) // TLS 1.3 ์ฌ์ฉ
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
}
์ค๋ช
- SSLContext ์ค์ :
SSLContextBuilder
๋ฅผ ์ฌ์ฉํ์ฌ TLS 1.3์ ์ค์ ํฉ๋๋ค.
SSLContext sslContext = SSLContextBuilder.create() .loadTrustMaterial(null, (chain, authType) -> true) // ๋ชจ๋ ์ธ์ฆ์๋ฅผ ์ ๋ขฐํ๋๋ก ์ค์ .build();
- PoolingHttpClientConnectionManager ๊ตฌ์ฑ:
PoolingHttpClientConnectionManagerBuilder
์DefaultClientTlsStrategy
๋ฅผ ์ฌ์ฉํ์ฌ SSL ์์ผ ํฉํ ๋ฆฌ๋ฅผ ์ค์ ํ๊ณ ์ฐ๊ฒฐ ํ์ ๊ตฌ์ฑํฉ๋๋ค.`
DefaultClientTlsStrategy tlsStrategy = new DefaultClientTlsStrategy(sslContext); PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() .setTlsStrategy(tlsStrategy) .setDefaultTlsConfig(tlsConfig -> tlsConfig .setHandshakeTimeout(Timeout.ofSeconds(30)) // ํธ๋์ ฐ์ดํฌ 30์ด ์ ํ .setSupportedProtocols(TLS.V_1_3)) // TLS 1.3 ์ฌ์ฉ .build();
- CloseableHttpClient ์์ฑ: ๊ตฌ์ฑ๋
PoolingHttpClientConnectionManager
๋ฅผ ์ฌ์ฉํ์ฌCloseableHttpClient
๋ฅผ ์์ฑํฉ๋๋ค.
CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(connectionManager) .build();
- HttpComponentsClientHttpRequestFactory ์ฌ์ฉ:
CloseableHttpClient
๋ฅผ ์ฌ์ฉํ์ฌHttpComponentsClientHttpRequestFactory
๋ฅผ ์์ฑํ๊ณ , ์ด๋ฅผRestTemplate
์ ์ค์ ํฉ๋๋ค. HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); return new RestTemplate(factory);
5. ํ ์คํธ ๋ฐ ์ฌ์ฉ
์ด์ ์ค์ ์ด ์๋ฃ๋ RestTemplate
๋น์ ์ฌ์ฉํ ์ค๋น๊ฐ ๋์์ต๋๋ค. RestTemplate
์ ์ฌ์ฉํ๋ ์๋น์ค ํด๋์ค์์ ์๋ ์ฃผ์
ํ์ฌ HTTPS ์์ฒญ์ ๋ณด๋ผ ์ ์์ต๋๋ค.
MyService.java
@Service
public class MyService {
@Autowired
private RestTemplate restTemplate;
public String getSecureData() {
ResponseEntity<String> response = restTemplate.getForEntity("https://secure.example.com/api/data", String.class);
return response.getBody();
}
}
6. ์ฐธ๊ณ ์๋ฃ
์ด๋ฒ ์ค์ ๋ณ๊ฒฝ ์ ์ setSSLSocketFactory
๋ฐ SSLConnectionSocketFactoryBuilder
์ deprecation ๋ฌธ์ ๊ฐ ์์ด ์ต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์๋ ๋ ์ด์ ๊ถ์ฅ๋์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋์ ํ์ฌ DefaultClientTlsStrategy
์ PoolingHttpClientConnectionManagerBuilder
๋ฅผ ์ฌ์ฉํ์ฌ TLS ์ค์ ์ ๊ตฌ์ฑํ์์ต๋๋ค.
'setSSLSocketFactory(org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory)' is deprecated
'org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder' is deprecated
Apache HttpComponents Migration Guide๋ฅผ ์ฐธ๊ณ ํ์ฌ ํด๊ฒฐํ์ต๋๋ค.
๋ง๋ฌด๋ฆฌ
mac springboot ๋ก์ปฌ ๊ฐ๋ฐ ํ๊ฒฝ์์ SSL ์ธ์ฆ์ ์์ฑํ๊ธฐ (mkcert ์ฌ์ฉ)
๋ก์ปฌ ๊ฐ๋ฐ ํ๊ฒฝ์์ HTTPS๋ฅผ ์ค์ ํ๋ ๊ฒ์ ๋ณด์ ํ ์คํธ์ ์ค์ ๋ฐฐํฌ ํ๊ฒฝ๊ณผ์ ์ผ๊ด์ฑ์ ์ ์งํ๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด๋ฒ ํฌ์คํธ์์๋ mkcert๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ขฐํ ์ ์๋ ๋ก์ปฌ SSL ์ธ์ฆ์๋ฅผ ์
jakezo.tistory.com
๊ณผ ๋ง์ด ์ฐ๊ณ๊ฐ ๋๋ ๋ด์ฉ์ด๋ค. ์ค์ ๋ก ๋๋ ์ด์ ์ค์ (SSL)์ ํ ํ์ ์ด ํฌ์คํ ๋ด์ฉ์ ์งํํ๊ธฐ ๋๋ฌธ์ด๋ค.
TLS 1.3 HttpComponents SSL ๋ฑ ๋ง๋ก๋ง ๋ค์์ง ์ ๋ฆฌ๊ฐ ์๋ ๋ด์ฉ๋ค์ด ๋ง์๋๋ฐ ์ด๋ฒ ํฌ์คํ ์ ํ๋ฉด์ ๋ค์ ์ ๋ฆฌํด๋ณด๋ ๊ธฐํ๋ฅผ ๊ฐ์ ธ์ ์ข์๋ค.
์น๊ฐ๋ฐ์ ํ๋ค๋ณด๋ฉด ๊ผญ ๊ตฌ์ฑํด์ผํ๋ ๋ด์ฉ์ด๊ธฐ์(SSL ์ธํ ์ ํ์ง์์ผ๋ฉด ํฌ๋กฌ๋ฑ ์ฌ๋ฌ๊ณณ์์ ๋ถ์ด์ต์ด ์์ ์ ์๋ค.) ์ ๋ฆฌ๊ฐ ๊ผญ ํ์ํ๋ค.
๋ํ setSSLSocketFactory
๋ฐ SSLConnectionSocketFactoryBuilder
๊ฐ deprecated ๋์๋ค๋ ๋ด์ฉ๋ ์๋ฌด๋ฆฌ stackoverflow ๋ก ๊ฒ์์ ํด๋ ๋์ค์ง ์์๋๋ฐ,
์ญ์ ์ด๋ด๋๋ ๊ณต์ ๋ฌธ์๋ฅผ ๋ณด๋๊ฒ ๋ง๋ค๋ ์๊ฐ์ด ๋ค์๋ค.