我尝试使用'javax.xml.ws.endpoint'类在Java中的2种方式部署Web服务。我的SSL设置非常限制。我必须设置一组特定的选项和设置。这是我无法讨论的要求。
为了设置SSL,我需要提供服务器上下文对象。进行了一些搜索后,我最终使用了" 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包中的什么?(,我发现它似乎在"太阳。"one_answers" com.sun。"的软件包之间有所不同。仍然没有确定的(记录(答案。请给出您的答案。
问题2:如果我不应该使用" com.sun.net.httpserver.httpsserver"类,我应该/应该使用什么?
注意:我不想使用容器(例如Tomcat,Jetty,...(。我不会解释原因。那是不合理的。
使用com.sun.net
软件包HTTP服务器没有任何问题,除了它不是JDK规格的一部分,这只是更多代码,即Oracle Bundle将其插入其发行版。您不会在OpenJDK中找到这些课程,但这与Tomcat或Jetty没有什么不同。使用sun
或com.sun
软件包的问题一直是它们不是JDK规格的一部分,它们是实现各种JDK组件或仅提供的内容的代码,因为它们是好人/GALS。有关sun.
和com.sun
我个人会避免使用它,因为有更好的选择。您可以将端点作为战争文件包装,并部署到servlet引擎,或使用Spring Boot/Dropwizard将Servlet Engine捆绑到大罐子中。
我会看使用经过战斗测试的非阻止IO的servlet引擎,并具有更好的管理和操作控制。已经提到的是Jetty和Tomcat,它们都非常好,还有JBoss Wildfly和许多其他商业选择(Weblogic,WebSphere,可能是成千上万的(
所有这些都将使您可以进行2向SSL,许多这些都可以重新使用现有的KeyStore
和TrustStore
代码。
Spring Boot有一个不错的肥皂示例,您会发现相同的方法适用于许多其他Servlet引擎。
启动jdk9(以及JDK8的最新版本(,有一个名为'jdeps'的工具,可提供选项'-jdkinternals'。使用我的代码使用它不会报告。这意味着(根据问题,使用-jdkinternals时jdeps no输出('com.sun.net.httpserver.httpsserver'不是内部类。