Spring/Spring 이야기
localhost HTTPS 적용 (spring boot)
seungdols
2023. 7. 31. 10:41
mkcert install
brew install mkcert
brew install nss # firefox 사용 예정이라면, 추가
mkcert localhost
명령어
mkcert -install [-uninstall 삭제]
> mkcert -install
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox trust store (requires browser restart)! 🦊
> mkcert -pkcs12 localhost
Created a new certificate valid for the following names 📜
- "localhost"
The PKCS#12 bundle is at "./localhost.p12" ✅
The legacy PKCS#12 encryption password is the often hardcoded default "changeit" ℹ️
It will expire on 26 October 2025 🗓
> mkcert localhost
Created a new certificate valid for the following names 📜
- "localhost"
The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" ✅
It will expire on 26 October 2025 🗓
spring boot config - application.yml
server:
port: 8080
ssl:
enabled: true
key-store: classpath:cert/localhost.p12
key-store-type: PKCS12
key-store-password: changeit # 비밀번호 지정 안한 경우
HTTPS open feign 오류시
server:
port: 8080
ssl:
enabled: true
key-store: classpath:cert/localhost.p12
key-store-type: PKCS12
key-store-password: changeit
http2:
enabled: true
@Component
class FeignClientConfiguration(
val serverProperties: ServerProperties,
@Value("\${server.ssl.key-store}") val keyStore: Resource
) {
@Bean
@Throws(Exception::class)
fun feignClient(): Client {
val keyStorePassword = serverProperties.ssl.keyStorePassword
return try {
Client.Default(
sslSocketFactory(keyStore.inputStream, keyStorePassword),
null
)
} catch (e: Exception) {
throw Exception("Error in initializing feign client", e)
}
}
@Throws(NoSuchAlgorithmException::class, KeyStoreException::class, CertificateException::class, IOException::class, KeyManagementException::class)
private fun sslSocketFactory(trustStoreStream: InputStream, trustStorePassword: String): SSLSocketFactory? {
val sslContext: SSLContext = SSLContext.getInstance("TLSv1.2")
val tmf = createTrustManager(trustStoreStream, trustStorePassword)
sslContext.init(arrayOf<KeyManager>(), tmf.trustManagers, null)
return sslContext.socketFactory
}
@Throws(KeyStoreException::class, IOException::class, NoSuchAlgorithmException::class, CertificateException::class)
private fun createTrustManager(trustStoreStream: InputStream, trustStorePassword: String): TrustManagerFactory {
val trustStore: KeyStore = KeyStore.getInstance(KeyStore.getDefaultType())
trustStore.load(trustStoreStream, trustStorePassword.toCharArray())
val tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(trustStore)
return tmf
}
}
위 코드에서 아래처럼 작성 하면 오류가 발생한다.
val keyStoreResource: Resource = ClassPathResource(serverProperties.ssl.keyStore)
Caused by: java.io.FileNotFoundException: class path resource [classpath:cert/localhost.p12] cannot be opened because it does not exist
원인은 그렇다. ClassPathResource
를 이용하면, classpath:
prefix가 없는 경로를 써넣어주어야 정상적으로 동작 하게 된다.
@Component
class FeignClientConfiguration(
@Value("\${server.ssl.key-store}") val keyStore: Resource,
@Value("\${server.ssl.key-store-password}") val keyStorePassword: String
) {
@Bean
@Throws(Exception::class)
fun feignClient(): Client {
return try {
Client.Default(
sslSocketFactory(keyStore.inputStream, keyStorePassword),
null
)
} catch (e: Exception) {
throw Exception("Error in initializing feign client", e)
}
}
@Throws(NoSuchAlgorithmException::class, KeyStoreException::class, CertificateException::class, IOException::class, KeyManagementException::class)
private fun sslSocketFactory(trustStoreStream: InputStream, trustStorePassword: String): SSLSocketFactory? {
val sslContext: SSLContext = SSLContext.getInstance("TLSv1.2")
val tmf = createTrustManager(trustStoreStream, trustStorePassword)
sslContext.init(arrayOf<KeyManager>(), tmf.trustManagers, null)
return sslContext.socketFactory
}
@Throws(KeyStoreException::class, IOException::class, NoSuchAlgorithmException::class, CertificateException::class)
private fun createTrustManager(trustStoreStream: InputStream, trustStorePassword: String): TrustManagerFactory {
val trustStore: KeyStore = KeyStore.getInstance(KeyStore.getDefaultType())
trustStore.load(trustStoreStream, trustStorePassword.toCharArray())
val tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(trustStore)
return tmf
}
}
굳이 ServerProperties
를 쓰지 않고, @Value
를 이용해서 가져오는 방법도 있다.
반응형