[英]'javax.xml.ws.Endpoint' and 2 ways SSL
我嘗試使用類'javax.xml.ws.Endpoint'在Java中使用2種方式部署Web服務。 我的SSL設置非常嚴格。 我必須設置一組特定的選項和設置。 這是我無法討論的要求。
為了設置SSL,我需要提供一個Server Context對象。 在做了一些搜索之后,我最終使用了類'com.sun.net.httpserver.HttpsServer'(以及其他一些相關的類也在包'com.sun'中)。 它在Windows JVM和HPUX JVM上運行良好。
但是,我知道(我應該說,我相信)不應該使用包'com.sun'中的類,因為它們不是標准運行時環境的一部分。 可以在不事先通知的情況下移動/修改/刪除這些類,並且依賴於JVM實現。
我的實際代碼是:
private static HttpsServer createHttpsServer() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException, NoSuchProviderException {
final String keyStoreType = "...";
final String keyStoreFile = "...";
final String keyStorePassword = "...";
final String trustStoreType = "...";
final String trustStoreFile = "...";
final String trustStorePassword = "...";
final String hostName = "...";
final int portNumber = "...;
final String sslContextName = "TLSv1.2";
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(new FileInputStream(keyStoreFile), keyStorePassword.toCharArray());
KeyStore trustStore = KeyStore.getInstance(trustStoreType);
trustStore.load(new FileInputStream(trustStoreFile), trustStorePassword.toCharArray());
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, keyStorePassword.toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance(sslContextName);
sslContext.init(keyFactory.getKeyManagers(), trustFactory.getTrustManagers(), getSecureRandom(pConfiguration));
HttpsServer httpsServer = HttpsServer.create(new InetSocketAddress(hostName, portNumber), portNumber);
HttpsConfigurator configurator = getHttpsConfigurator(pConfiguration, sslContext);
httpsServer.setHttpsConfigurator(configurator);
httpsServer.start();
return httpsServer;
}
private static Endpoint publishSsl(final HttpsServer pHttpsServer, final String pPath, final Object implementationObject) {
LOGGER.entering(LOGGER_SOURCE_CLASS, "publishSsl");
HttpContext httpContext = pHttpsServer.createContext(pPath);
Endpoint endPoint = Endpoint.create(implementationObject);
endPoint.publish(httpContext);
return endPoint;
}
private static HttpsConfigurator getHttpsConfigurator(final MyProperties pConfiguration, SSLContext pSslContext) {
EnforcingHttpsConfigurator configurator = new EnforcingHttpsConfigurator(pSslContext);
// Those are hidden properties to override the SSL configuration if needed.
final String ciphers = pConfiguration.getProperty("overrideSslConfiguration.ciphers", "");
final boolean needClientAuth = pConfiguration.getPropertyAsBoolean("overrideSslConfiguration.needClientAuth", true);
final String protocols = pConfiguration.getProperty("overrideSslConfiguration.protocols", "");
if (!ciphers.isEmpty()) {
configurator.setCiphers(ciphers);
}
configurator.setNeedClientAuth(needClientAuth);
if (!protocols.isEmpty()) {
configurator.setProtocols(protocols);
}
return configurator;
}
public class EnforcingHttpsConfigurator extends HttpsConfigurator {
private static final Logger LOGGER = Logger.getLogger(EnforcingHttpsConfigurator.class.getCanonicalName());
private static final String LOGGER_SOURCE_CLASS = EnforcingHttpsConfigurator.class.getName();
private String mProtocols = "TLSv1.2";
private String mCiphers = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_GCM_SHA256";
private boolean mNeedClientAuth = true;
public EnforcingHttpsConfigurator(SSLContext pSslContext) {
super(pSslContext);
}
public String getProtocols() {
return mProtocols;
}
public void setProtocols(String pProtocols) {
LOGGER.warning("Override SSL configuration, Set protocols '" + pProtocols + "'. This is potentially unsafe.");
mProtocols = pProtocols;
}
public String getCiphers() {
return mCiphers;
}
public void setCiphers(String pCiphers) {
LOGGER.warning("Override SSL configuration, Set ciphers '" + pCiphers + "'. This is potentially unsafe.");
mCiphers = pCiphers;
}
public boolean isNeedClientAuth() {
return mNeedClientAuth;
}
public void setNeedClientAuth(boolean pNeedClientAuth) {
if (!pNeedClientAuth) {
LOGGER.warning("Override SSL configuration, no client authentication required. This is potentially unsafe.");
}
mNeedClientAuth = pNeedClientAuth;
}
@Override
public void configure(HttpsParameters params) {
LOGGER.entering(LOGGER_SOURCE_CLASS, "configure");
final SSLContext context = getSSLContext();
final SSLParameters sslParams = context.getDefaultSSLParameters();
// Override current values
sslParams.setCipherSuites(mCiphers.split(","));
sslParams.setProtocols(mProtocols.split(","));
sslParams.setNeedClientAuth(mNeedClientAuth);
params.setSSLParameters(sslParams);
LOGGER.exiting(LOGGER_SOURCE_CLASS, "configure");
}
}
問題1:聲明'不應該使用com.sun中的類'是否有效? 我解釋的原因是什么? 從我的搜索(例如什么是com.sun包里面? ),我發現它似乎與包'sun之間有區別。 '和'com.sun。 ”。 仍然沒有明確(記錄)的答案。 請為您的答案提供參考。
問題2:如果我不使用“com.sun.net.httpserver.HttpsServer”類,我可以/應該使用什么?
注意:我不想使用容器(如Tomcat,Jetty,......)。 我不會解釋原因。 這不是主題。
使用com.sun.net
包HTTP服務器沒有問題,除了它不是JDK規范的一部分,它只是Oracle捆綁到其分發中的更多代碼。 你不會在OpenJDK中找到這些類,但它與tomcat或jetty沒有什么不同。 使用sun
或com.sun
包的問題一直是它們不是JDK規范的一部分,它們是實現各種JDK組件的代碼,或者只是它們提供的東西,因為它們是好人/ gals。 有關sun.
詳細信息,請參閱Oracle的 此問題和此常見問題解答 sun.
和com.sun
我個人會避免它,因為有更好的選擇。 您可以將Endpoint打包為WAR文件並部署到servlet引擎或使用Spring Boot / Dropwizard將servlet引擎捆綁到一個大的jar文件中。
我會看一下使用經過戰斗測試的非阻塞IO的servlet引擎,並且具有更好的管理和操作控制。 已經提到Jetty和Tomcat都非常好,還有JBoss Wildfly和一些其他商業選項(WebLogic,Websphere,可能還有數千個)
所有這些都允許您執行雙向SSL,許多將允許您重用現有的KeyStore
和TrustStore
代碼。
Spring Boot有一個很好的SOAP示例 ,您會發現相同的方法適用於許多其他servlet引擎。
啟動JDK9(以及最新版本的JDK8),有一個名為'jdeps'的工具,它提供了選項'-jdkinternals'。 對我的代碼使用它將不會報告任何內容。 這意味着(根據問題,使用-jdkinternals時沒有帶jdeps的輸出 )'com.sun.net.httpserver.HttpsServer'不是內部類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.