我正在研究一个代码,该代码通过充当MITM的代理连接到Slack证书,并用其自己的自签名证书替换Slack证书。我将代理的证书添加到信任库中,并将RestTemplate配置为使用信任库:
def sslContext = new SslContextBuilder().withTrustStore(trustStoreResource, trustStorePassword).build()
def proxy = proxyEnabled ? new HttpHost(proxyHost, proxyPort) : null
def httpClient = HttpClients.custom().setProxy(proxy).setSSLContext(sslContext).build()
def result = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient))
很好。但是,在我的本地计算机上,我不会通过代理直接连接到Slack。换句话说,以上代码中的httpClient将配置为SSLContext而不是代理。我期望这会很好,因为Slack的证书已使用有效的根CA签名,但是我的代码无法验证Slack的证书。
我以为这是因为我的托拉斯,但是我对为什么会这样感到困惑。是否因为根CA未导入我的托管库中而发生?如果是这样,我该怎么做而不必维护根CA?
我知道在本地可以避免建立信任库,但如果可能的话,我想避免在代码中添加分支。
我最终最终要做的是使用https://gist.github.com/JensRantil/9b7fecb3647ecf1e3076中的实现将系统的默认信任库与我的合并,然后使用以下类构建我的SSL上下文。遗憾的是HttpClient不提供此功能,但可能有充分的理由。
import org.springframework.core.io.Resource
import javax.net.ssl.KeyManager
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import java.security.KeyStore
class SslContextBuilder {
private KeyManager[] keyManagers = []
private TrustManager[] trustManagers = []
SslContextBuilder withKeyStore(Resource resource, String password) {
def keyStore = KeyStore.getInstance('JKS')
keyStore.load(resource.getInputStream(), password.chars)
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmfactory.init(keyStore, password.chars)
KeyManager[] kms = kmfactory.getKeyManagers()
keyManagers += kms ? kms : []
this
}
SslContextBuilder withTrustStore(Resource resource, String password) {
def trustStore = KeyStore.getInstance('JKS')
trustStore.load(resource.getInputStream(), password.chars)
def tss = CompositeX509TrustManager.getTrustManagers(trustStore)
trustManagers += tss ? tss : []
this
}
SSLContext build() {
def sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null)
sslContext
}
}