我目前正在使用CXF rev 3.1.10开发SOAP-Server / Client。 只要我不尝试使用https,一切都已设置并且工作正常。 我没有使用任何xml文件/ bean,除了框架可能在“幕后”使用的那些。
我真的想这样离开。
我正在使用自签名证书及其提取的密钥,以防万一这可能是必要的。
public class Server扩展Thread {
private static final Logger LOG = Logger.getLogger(Server.class);
@WebService(name = "SoapService", serviceName = "SoapService", endpointInterface = "playground.mstahl.cxf_soap.SoapServiceDefinition")
private static final class ServerImpl implements SoapServiceDefinition {
@Override
public boolean handleStateDataRecipience(String user, String pass, String restri) throws Exception {
return true;
}
}
private final int usedPort;
private final String ksPath;
private final String ksPass;
private final boolean sslEnabled;
public Server(int port, boolean sslEnabled, String ksPath, String ksPass) {
super("CXF-SOAP-Playground");
setDaemon(true);
usedPort = port;
this.sslEnabled = sslEnabled;
this.ksPath = ksPath;
this.ksPass = ksPass;
start();
}
@Override
public void run() {
JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
sf.setAddress(String.format("http" + (sslEnabled ? "s" : "") + "://localhost:%d/signtest/", Integer.valueOf(usedPort))); // <- Yah, pretty ugly, but its just for testing purposes ;)
sf.setServiceClass(ServerImpl.class);
ServerImpl serviceBean = new ServerImpl();
sf.setServiceBean(serviceBean);
if (sslEnabled) {
try {
JettyHTTPServerEngineFactory factory = sf.getBus().getExtension(JettyHTTPServerEngineFactory.class);
factory.setTLSServerParametersForPort(usedPort, getTLSServerParameters(ksPath, ksPass));
} catch (Exception e) {
e.printStackTrace();
}
}
org.apache.cxf.endpoint.Server server = sf.create();
if (!server.isStarted()) {
return;
}
LOG.debug("... done.");
while (!IsInterrupted()) {
try {
Thread.sleep(100);
} catch (Exception e) {
//meh, just a test
}
}
server.stop();
server.destroy();
}
private final TLSServerParameters getTLSServerParameters(final String ksPath, final String ksPass) {
TLSServerParameters tlsParams = null;
try {
tlsParams = new TLSServerParameters();
File truststore = new File(ksPath);
LOG.info("Try to load file " + truststore.getCanonicalPath());
final KeyStore keyStore = KeyStore.getInstance("JKS");
FileInputStream stream = new FileInputStream(truststore);
final char[] keyStorePassphraseAsChar = ksPass.toCharArray();
keyStore.load(stream, keyStorePassphraseAsChar);
stream.close();
final KeyManagerFactory keyFactory = KeyManagerFactory.getInstance("PKIX");
keyFactory.init(keyStore, keyStorePassphraseAsChar);
final KeyManager[] km = keyFactory.getKeyManagers();
tlsParams.setKeyManagers(km);
truststore = new File(ksPath);
stream = new FileInputStream(truststore);
keyStore.load(stream, keyStorePassphraseAsChar);
stream.close();
final TrustManagerFactory trustFactory = TrustManagerFactory.getInstance("PKIX");
trustFactory.init(keyStore);
final TrustManager[] tm = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(tm);
final SSLContext context = SSLContext.getDefault();
final SSLSocketFactory sf = context.getSocketFactory();
final List<String> cipherSuites = Arrays.asList(sf.getSupportedCipherSuites());
LOG.info(String.format("Suppored cipher suites : %s", cipherSuites.toString()));
final FiltersType filter = new FiltersType();
final List<String> include = filter.getInclude();
include.add(".*_EXPORT_.*");
include.add(".*_EXPORT1024_.*");
include.add(".*_WITH_DES_.*");
include.add(".*_WITH_AES_.*");
include.add(".*_WITH_NULL_.*");
include.add(".*_RSA_WITH_AES_.*");
include.add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
final ClientAuthentication ca = new ClientAuthentication();
ca.setRequired(false);
ca.setWant(false);
tlsParams.setClientAuthentication(ca);
} catch (final Exception e) {
LOG.error("Security configuration failed with the following: " + e.getMessage() + " " + e.getCause());
tlsParams = null;
}
return tlsParams;
}
}
我的服务器目前启动很好。 (至少没有错误被抛出......) 只要我使用http ...
,我也可以访问给定的soap方法public class Client {
private static final Logger LOG = Logger.getLogger(Client.class);
private static SoapServiceDefinition client;
public Client(String address, boolean sslEnabled, String ksFile, String ksPass) {
// set keystore setting for plain httpclient
if (sslEnabled) {
LOG.debug(" ... collecting keystore file and passphrase due to enabled ssl.");
System.setProperty("javax.net.ssl.keyStore", ksFile);
System.setProperty("javax.net.ssl.trustStore", ksFile);
System.setProperty("javax.net.ssl.keyStorePassword", ksPass);
System.setProperty("javax.net.ssl.trustStorePassword", ksPass);
}
LOG.debug(" ... creating service factory.");
final JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(SoapServiceDefinition.class);
LOG.debug(" ... setting host address to '" + address + "'.");
factory.setAddress(address);
LOG.debug(" ... creating actual SOAP-client.");
client = (SoapServiceDefinition) factory.create();
final HTTPConduit httpConduit = (HTTPConduit) ClientProxy.getClient(client).getConduit();
if (sslEnabled) {
LOG.debug(" ... configuring SSL.");
configureClientSideSSL(httpConduit, ksFile, ksPass);
LOG.debug(" ... done.");
}
LOG.debug(" ... setting timeouts.");
final HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(0);
httpClientPolicy.setReceiveTimeout(0);
httpClientPolicy.setContentType("application/soap+xml");
httpConduit.setClient(httpClientPolicy);
retrieveAndStoreWSDL(address);
}
private void configureClientSideSSL(final HTTPConduit conduit, final String keyStorePath, final String trustpass) {
try {
final TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setDisableCNCheck(true);
final KeyStore keyStore = KeyStore.getInstance("jceks");
final File truststore = new File(keyStorePath);
final FileInputStream stream = new FileInputStream(truststore);
keyStore.load(stream, trustpass.toCharArray());
final TrustManagerFactory trustFactory = TrustManagerFactory.getInstance("PKIX");
trustFactory.init(keyStore);
final TrustManager[] tm = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(tm);
final KeyManagerFactory keyFactory = KeyManagerFactory.getInstance("PKIX");
keyFactory.init(keyStore, trustpass.toCharArray());
final KeyManager[] km = keyFactory.getKeyManagers();
tlsParams.setKeyManagers(km);
final FiltersType filter = new FiltersType();
final List<String> include = filter.getInclude();
include.add(".*");
include.add(".*_EXPORT_.*");
include.add(".*_EXPORT1024_.*");
include.add(".*_WITH_DES_.*");
include.add(".*_WITH_AES_.*");
include.add(".*_WITH_NULL_.*");
include.add(".*_RSA_WITH_AES_.*");
include.add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
conduit.setTlsClientParameters(tlsParams);
stream.close();
} catch (final Exception e) {
System.out.println("Security configuration failed with the following: " + e.getCause());
}
}
private void retrieveAndStoreWSDL(final String address) {
LOG.info(" ... retrieving the WSDL-file.");
final HttpClient httpclient = new HttpClient();
httpclient.getParams().setSoTimeout(0); // No timeout at all...in case of big wsdls
final GetMethod get = new GetMethod(address);
get.setQueryString("?wsdl");
try {
final int result = httpclient.executeMethod(get);
final String str = IOUtils.toString(get.getResponseBodyAsStream(), "UTF-8");
LOG.debug(" ... Response status code: " + result);
} catch (final Throwable e) {
LOG.debug("-", e);
LOG.error(e.getClass().getSimpleName() + " occurred during WSDL-retrieval. Won't store current WSDL.");
} finally {
get.releaseConnection();
}
}
public String helloReturn() throws Exception {
return "haha:" + client.handleStateDataRecipience("", "", "");
}
}
客户端也在努力,但是,当客户端尝试检索WSDL和/或尝试执行其获得的任何方法时:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
...
正如我之前提到的,只要我使用http而不是https,一切正常。
我不认为这个问题是关键存储,因为我最终可以通过使用它来阅读它们并获得它们的密钥。
private static void displayKeys(String ksForm, String alias, char[] ksPass, char[] kePass, String keystore) throws Exception {
System.out
.println("---------------------------------------------------------------------------------------------------------------------------");
KeyStore keyStore = KeyStore.getInstance(ksForm);
keyStore.load(new FileInputStream(keystore), ksPass);
Key key = keyStore.getKey(alias, kePass);
if (key instanceof PrivateKey) {
System.out.println("Get private key : ");
System.out.println(key.toString());
java.security.cert.Certificate[] certs = keyStore.getCertificateChain(alias);
System.out.println("Certificate chain length : " + certs.length);
for (Certificate cert : certs) {
System.out.println(cert.toString());
}
} else {
System.out.println("Get public key : ");
System.out.println(key.toString());
}
System.out
.println("---------------------------------------------------------------------------------------------------------------------------");
}
Caused by: java.io.EOFException: SSL peer shut down incorrectly
提前致谢并致以亲切的问候。
答案 0 :(得分:1)
所以,我终于弄清楚了。 实际上手头有几个问题
下面我将为您提供我用于获得完整运行示例的所有类的代码。
由于我一直遇到SunAPI及其证书创建代码示例的问题,我决定改用BouncyCastle。
尽管我之前决定不使用第三方工具,但由于我仅将其用于密钥库/证书创建,我改变了主意。
您将要看到的课程是“Maarten Bodewes”对此问题的回答的略微修改版本:
How to store and reuse keypair in Java?
该课程非常简单,因此没有添加任何方法评论......
package playground.TEST.cxf_soap;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStore.Entry;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.UnrecoverableEntryException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Calendar;
import java.util.Date;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class BCCertUtils {
public static KeyPair generateKeyPair(int keySize, String keyAlgo, String secureAlgo) throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(keyAlgo != null && !keyAlgo.trim().isEmpty() ? keyAlgo : "RSA");
keyGen.initialize(keySize, secureAlgo != null && !secureAlgo.trim().isEmpty() ? SecureRandom.getInstance(secureAlgo) : new SecureRandom());
KeyPair pair = keyGen.generateKeyPair();
return pair;
}
public static Certificate generateSelfSignedCertificate(KeyPair keyPair, String dn, String sigAlg, Date endDate)
throws OperatorCreationException, CertificateException {
// Setting bouncy castle provider to be able to create certs at all...
Provider bcProvider = new BouncyCastleProvider();
Security.addProvider(bcProvider);
X500Name dnName = new X500Name(dn);
// Using the current timestamp as the certificate serial number
BigInteger certSerialNum = new BigInteger(String.valueOf(System.currentTimeMillis()));
// Setting start date
Date startDate = Calendar.getInstance().getTime();
// Use appropriate signature algorithm based on your keyPair algorithm.
String sigAlgorithm = sigAlg == null || sigAlg.trim().isEmpty() ? "SHA256WithRSA" : sigAlg;
SubjectPublicKeyInfo certPubKey = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(dnName, certSerialNum, startDate, endDate, dnName, certPubKey);
ContentSigner contentSigner = new JcaContentSignerBuilder(sigAlgorithm).setProvider(bcProvider).build(keyPair.getPrivate());
X509CertificateHolder certificateHolder = certBuilder.build(contentSigner);
return new JcaX509CertificateConverter().getCertificate(certificateHolder);
}
public static void storeToPKCS12File(String alias, Certificate selfCert, String filename, char[] ksPass, char[] kePass, PrivateKey privKey)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, OperatorCreationException {
KeyStore p12Store = createP12Store(alias, selfCert, privKey, kePass);
try (FileOutputStream fos = new FileOutputStream(filename)) {
p12Store.store(fos, ksPass);
}
}
public static byte[] storeToPKCS12ByteArray(String alias, Certificate selfCert, char[] ksPass, char[] kePass, PrivateKey privKey)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, OperatorCreationException {
KeyStore p12Store = createP12Store(alias, selfCert, privKey, kePass);
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
p12Store.store(bos, ksPass);
return bos.toByteArray();
}
}
private static KeyStore createP12Store(String alias, Certificate selfCert, PrivateKey privKey, char[] kePass)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore p12KeyStore = KeyStore.getInstance("PKCS12");
p12KeyStore.load(null, null);
KeyStore.Entry entry = new PrivateKeyEntry(privKey, new Certificate[] { selfCert });
KeyStore.ProtectionParameter param = new KeyStore.PasswordProtection(kePass);
p12KeyStore.setEntry(alias, entry, param);
return p12KeyStore;
}
public static boolean moduliMatch(PublicKey originPubKey, PrivateKey certPrivKey) {
return ((RSAPublicKey) originPubKey).getModulus().equals(((RSAPrivateKey) certPrivKey).getModulus());
}
public static KeyPair loadKeysFromPKCS12File(String alias, String filename, char[] storePass, char[] entryPass) throws KeyStoreException,
NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableEntryException {
KeyStore pkcs12KeyStore = KeyStore.getInstance("PKCS12");
try (FileInputStream fis = new FileInputStream(filename);) {
pkcs12KeyStore.load(fis, storePass);
}
return loadKeyPair(pkcs12KeyStore, alias, entryPass);
}
public static KeyPair loadKeysFromPKCS12ByteArray(String alias, byte[] storeBytes, char[] storePass, char[] entryPass) throws KeyStoreException,
NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableEntryException {
KeyStore pkcs12KeyStore = KeyStore.getInstance("PKCS12");
try (ByteArrayInputStream bis = new ByteArrayInputStream(storeBytes);) {
pkcs12KeyStore.load(bis, storePass);
}
return loadKeyPair(pkcs12KeyStore, alias, entryPass);
}
private static KeyPair loadKeyPair(KeyStore ks, String alias, char[] entryPass)
throws NoSuchAlgorithmException, UnrecoverableEntryException, KeyStoreException {
KeyStore.ProtectionParameter param = new KeyStore.PasswordProtection(entryPass);
Entry entry = ks.getEntry(alias, param);
if (!(entry instanceof PrivateKeyEntry)) {
throw new KeyStoreException("That's not a private key!");
}
PrivateKeyEntry privKeyEntry = (PrivateKeyEntry) entry;
PublicKey publicKey = privKeyEntry.getCertificate().getPublicKey();
PrivateKey privateKey = privKeyEntry.getPrivateKey();
return new KeyPair(publicKey, privateKey);
}
public static Certificate loadCertFromPKCS12File(String alias, String filename, char[] storePass, char[] entryPass) throws KeyStoreException,
NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableEntryException {
KeyStore pkcs12KeyStore = KeyStore.getInstance("PKCS12");
try (FileInputStream fis = new FileInputStream(filename);) {
pkcs12KeyStore.load(fis, storePass);
}
return loadCert(pkcs12KeyStore, alias, entryPass);
}
public static Certificate loadCertFromPKCS12ByteArray(String alias, byte[] storeBytes, char[] storePass, char[] entryPass)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException,
UnrecoverableEntryException {
KeyStore pkcs12KeyStore = KeyStore.getInstance("PKCS12");
try (ByteArrayInputStream bis = new ByteArrayInputStream(storeBytes);) {
pkcs12KeyStore.load(bis, storePass);
}
return loadCert(pkcs12KeyStore, alias, entryPass);
}
private static Certificate loadCert(KeyStore ks, String alias, char[] entryPass)
throws NoSuchAlgorithmException, UnrecoverableEntryException, KeyStoreException {
KeyStore.ProtectionParameter param = new KeyStore.PasswordProtection(entryPass);
Entry entry = ks.getEntry(alias, param);
if (!(entry instanceof PrivateKeyEntry)) {
throw new KeyStoreException("That's not a private key!");
}
PrivateKeyEntry privKeyEntry = (PrivateKeyEntry) entry;
return privKeyEntry.getCertificate();
}
public static void storeToPEMFile(Certificate pubCert, String certPath) throws IOException {
JcaPEMWriter pw = new JcaPEMWriter(new FileWriter(certPath));
pw.writeObject(pubCert);
pw.flush();
pw.close();
}
public static byte[] storeToPEMByteArray(Certificate pubCert) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(baos));
JcaPEMWriter pw = new JcaPEMWriter(writer);
pw.writeObject(pubCert);
pw.flush();
pw.close();
return baos.toByteArray();
}
}
这是我将实际生成密钥并启动服务器和客户端以及使用客户端方法的代码。
package playground.test.cxf_soap;
import java.security.KeyPair;
import java.security.cert.Certificate;
import java.util.Calendar;
public class Starter {
public static void main(String[] args) {
try {
boolean enableSSL = true;
char[] entryPass = "entryPass".toCharArray();
char[] storePass = "storePass".toCharArray();
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 100);
// Server Store and Client cert.
KeyPair srvKeyPair = BCCertUtils.generateKeyPair(2048, "RSA", "SHA1PRNG");
Certificate srvPrivCert = BCCertUtils.generateSelfSignedCertificate(srvKeyPair, "CN=Test", "SHA256WithRSA", calendar.getTime());
byte[] srvStoreBytes = BCCertUtils.storeToPKCS12ByteArray("alias", srvPrivCert, storePass, entryPass, srvKeyPair.getPrivate());
KeyPair SvrCertKeys = BCCertUtils.loadKeysFromPKCS12ByteArray("alias", srvStoreBytes, storePass, entryPass);
if (!BCCertUtils.moduliMatch(srvKeyPair.getPublic(), SvrCertKeys.getPrivate())) {
System.err.println("ARRGL");
return;
}
Certificate clientCert = BCCertUtils.loadCertFromPKCS12ByteArray("alias", srvStoreBytes, storePass, entryPass);
byte[] clientCertBytes = BCCertUtils.storeToPEMByteArray(clientCert);
Server server = new Server(443, enableSSL, srvStoreBytes, storePass, entryPass);
while (!server.isRunning()) {
Thread.sleep(10);
}
Client client = new Client("https://localhost:" + 443 + "/signtest/", enableSSL, clientCertBytes);
System.out.println("Hello SOAP-Server :)");
System.out.println(" -> " + client.helloReturn("Stahler"));
System.out.println("Could you tell me if it is working?");
System.out.println(" -> " + client.isItWorking());
System.out.println("Awww finally, thank you server and goodbye.");
System.out.println(" -> " + client.gbyeReturn("Stahler"));
System.exit(0);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
现在我将向您展示我的服务器类我在其中导入先前创建的PKCS12存储并调整TLS设置以使用客户端。 package playground.mstahl.cxf_soap;
import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.util.Arrays;
import java.util.List;
import javax.jws.WebService;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import org.apache.cxf.configuration.jsse.TLSServerParameters;
import org.apache.cxf.configuration.security.ClientAuthentication;
import org.apache.cxf.configuration.security.FiltersType;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngineFactory;
public class Server extends Thread {
private boolean isRunning = false;
@WebService(name = "SoapService", serviceName = "SoapService", endpointInterface = "playground.mstahl.cxf_soap.SoapServiceDefinition")
private static final class ServerImpl implements SoapServiceDefinition {
@Override
public String sayHelloToMe(String caller) throws Exception {
return "oh Hello " + caller + ".";
}
@Override
public String askFunctionality() throws Exception {
return "Well, as I am answering I guess its working...duh";
}
@Override
public String sayGoodbyeToMe(String caller) throws Exception {
return "Goodbye doucheb...i mean..." + caller + ".";
}
}
private final int usedPort;
private final byte[] storeBytes;
private final char[] storePass;
private final char[] entryPass;
private final boolean sslEnabled;
public Server(int port, boolean sslEnabled, byte[] storeBytes, char[] storePass, char[] entryPass) {
super("CXF-SOAP-Playground");
setDaemon(true);
usedPort = port;
this.sslEnabled = sslEnabled;
this.storeBytes = storeBytes;
this.storePass = storePass;
this.entryPass = entryPass;
start();
}
@Override
public void run() {
System.out.println(" ... creating factory.");
JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
System.out.println(" ... setting address and implementing service.");
sf.setAddress(String.format("http" + (sslEnabled ? "s" : "") + "://localhost:%d/signtest/", Integer.valueOf(usedPort)));
sf.setServiceClass(ServerImpl.class);
System.out.println(" ... setting up service bean.");
ServerImpl serviceBean = new ServerImpl();
sf.setServiceBean(serviceBean);
if (sslEnabled) {
try {
JettyHTTPServerEngineFactory factory = sf.getBus().getExtension(JettyHTTPServerEngineFactory.class);
factory.setTLSServerParametersForPort(usedPort, getTLSServerParameters());
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(" ... starting actual SOAP-server.");
org.apache.cxf.endpoint.Server server = sf.create();
Endpoint endpoint = server.getEndpoint();
String endpointAddr = endpoint.getEndpointInfo().getAddress();
System.out.println("Server started at " + endpointAddr);
if (!server.isStarted()) {
return;
}
isRunning = true;
System.out.println("... done.");
while (!isInterrupted()) {
try {
Thread.sleep(100);
} catch (Exception e) {
}
}
System.out.println("... stopping actual SOAP-server.");
server.stop();
System.out.println("... destroying its remnants.");
server.destroy();
}
public boolean isRunning() {
return isRunning;
}
private final TLSServerParameters getTLSServerParameters() {
TLSServerParameters tlsParams = null;
try {
// 1 - Load key store
KeyStore localKeyStore = KeyStore.getInstance("PKCS12");
localKeyStore.load(new ByteArrayInputStream(storeBytes), storePass);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(localKeyStore, entryPass);
// 2 - Add the new keyManager to the tls settings.
tlsParams = new TLSServerParameters();
tlsParams.setKeyManagers(kmf.getKeyManagers());
// 3 - Adjust cipher suite filters
final List<String> cipherSuites = Arrays.asList(SSLContext.getDefault().getSocketFactory().getSupportedCipherSuites());
System.out.println(String.format("Suppored cipher suites : %s", cipherSuites.toString()));
final FiltersType filter = new FiltersType();
final List<String> include = filter.getInclude();
include.add(".*");
include.add(".*_EXPORT1024_.*");
include.add(".*_WITH_DES_.*");
include.add(".*_WITH_AES_.*");
include.add(".*_WITH_NULL_.*");
include.add(".*_RSA_WITH_AES_.*");
include.add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
// 4 - Disable client authentication
final ClientAuthentication ca = new ClientAuthentication();
ca.setRequired(false);
ca.setWant(false);
tlsParams.setClientAuthentication(ca);
} catch (final Exception e) {
e.printStackTrace();
System.err.println("Security configuration failed with the following: " + e.getMessage() + " " + e.getCause());
tlsParams = null;
}
return tlsParams;
}
}
最后但并非最不重要的一个小客户端类,我在其中导入了之前从服务器密钥库导出的证书。 package playground.mstahl.cxf_soap;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.List;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.io.IOUtils;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.configuration.security.FiltersType;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.apache.System.out.println4j.System.out.printlnger;
public class Client {
private static SoapServiceDefinition client;
public Client(String address, boolean sslEnabled, byte[] remoteCertBytes) {
System.out.println(" ... creating service factory.");
final JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(SoapServiceDefinition.class);
System.out.println(" ... setting host address to '" + address + "'.");
factory.setAddress(address);
System.out.println(" ... creating actual SOAP-client.");
client = (SoapServiceDefinition) factory.create();
final HTTPConduit httpConduit = (HTTPConduit) ClientProxy.getClient(client).getConduit();
if (sslEnabled) {
System.out.println(" ... configuring SSL.");
configureClientSideSSL(httpConduit, remoteCertBytes);
System.out.println(" ... done.");
}
System.out.println(" ... setting timeouts.");
final HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(0);
httpClientPolicy.setReceiveTimeout(0);
httpClientPolicy.setContentType("application/soap+xml");
httpConduit.setClient(httpClientPolicy);
try {
retrieveAndStoreWSDL(sslEnabled, address);
} catch (Exception e) {
e.printStackTrace();
}
}
private void configureClientSideSSL(final HTTPConduit conduit, byte[] remoteCertBytes) {
TLSClientParameters tlsParams = null;
try {
// 1 - Load the remote certificate
ByteArrayInputStream bis = new ByteArrayInputStream(remoteCertBytes);
X509Certificate remoteCert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new BufferedInputStream(bis));
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry(Integer.toString(1), remoteCert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
// 2 - Add the new trustmanager to the tls settings.
tlsParams = new TLSClientParameters();
tlsParams.setTrustManagers(tmf.getTrustManagers());
// 3 - Disable CN check
tlsParams.setDisableCNCheck(true);
// 4 - Set default SSL-context (necessary for e.g. the wsdl retrieval)
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
SSLContext.setDefault(context);
final FiltersType filter = new FiltersType();
final List<String> include = filter.getInclude();
include.add(".*");
include.add(".*_EXPORT_.*");
include.add(".*_EXPORT1024_.*");
include.add(".*_WITH_DES_.*");
include.add(".*_WITH_AES_.*");
include.add(".*_WITH_NULL_.*");
include.add(".*_RSA_WITH_AES_.*");
include.add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
conduit.setTlsClientParameters(tlsParams);
} catch (final Exception e) {
e.printStackTrace();
System.out.println("Security configuration failed with the following: " + e.getCause());
}
}
private void retrieveAndStoreWSDL(boolean sslEnabled, final String address) throws Exception {
System.out.println(" ... retrieving the WSDL-file."); // TODO ssl enabled check (Necessary if we do this beforehand?)
URL wsdlUrl = new URL(address + "?wsdl");
URLConnection connection = wsdlUrl.openConnection();
HttpsURLConnection conn = (HttpsURLConnection) connection;
if (sslEnabled) {
conn.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
}
conn.setRequestMethod("GET");
conn.connect();
String wsdl = IOUtils.toString(conn.getInputStream(), Charset.defaultCharset());
System.err.println(wsdl);
conn.disconnect();
}
public String helloReturn(String caller) throws Exception {
return client.sayHelloToMe(caller);
}
public String isItWorking() throws Exception {
return client.askFunctionality();
}
public String gbyeReturn(String caller) throws Exception {
return client.sayGoodbyeToMe(caller);
}
}
感谢所有阅读我的问题并想到可能解决方案的人。 希望这可以帮助别人。 亲切的问候