Comment programmer le contexte SSL D'un client JAX-WS?
j'ai essayé d'ajouter un nouveau clavier à travers la configuration standard du système ( -Djavax.net.ssl.keyStore=xyz
) mais mes autres composants sont clairement affectés par cela. Bien que mes autres composants utilisent des paramètres dédiés pour leur configuration SSL ( my.xmpp.keystore=xxx, my.xmpp.truststore=xxy, ...
), il semble qu'ils finissent par utiliser le global SSLContext
. (Le namespace de configuration my.xmpp.
semble indiquer une séparation, mais ce n'est pas le cas)
j'ai également essayé d'ajouter mon certificat client dans mon keystore original, mais-encore une fois - mes autres composants ne semblent pas aimer non plus.
je pense que ma seule option est de programmer la configuration JAX-WS HTTPS pour configurer le keystore et la truststore pour l'interaction client JAX-WS.
des idées / conseils pour faire cela? Toutes les informations que je trouve soit utilise la méthode javax.net.ssl.keyStore
ou mondial SSLContext
qui -je pense - se retrouvent dans la même confilc. Le plus proche que j'ai eu de quelque chose d'utile était ce vieux rapport de bogue qui demande la fonctionnalité dont j'ai besoin: ajouter le support pour passer un SSLContext au client JAX-WS runtime
quelque chose?
8 réponses
celui-ci était un écrou difficile à briser, donc pour rappel:
pour résoudre ce problème, il a fallu une coutume KeyManager
et un SSLSocketFactory
qui utilise cette coutume KeyManager
pour accéder au séparé KeyStore
.
J'ai trouvé le code de base pour ce KeyStore
et SSLFactory
sur cet excellent billet de blog:
comment est-à-dynamiquement-choisir-un-certificat-alias-quand-invoquer-web-services
puis, les spécialistes SSLSocketFactory
doit être inséré dans le contexte WebService:
service = getWebServicePort(getWSDLLocation());
BindingProvider bindingProvider = (BindingProvider) service;
bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", getCustomSocketFactory());
où le getCustomSocketFactory()
renvoie un SSLSocketFactory
créé en utilisant la méthode mentionnée ci-dessus. Cela ne fonctionnerait que pour JAX-WS RI à partir de L'impl Sun-Oracle intégré dans le JDK, étant donné que la chaîne de caractères indiquant la propriété SSLSocketFactory
est propriétaire pour cette implémentation.
à ce stade, la communication de service JAX-WS est sécurisée par SSL, mais si vous êtes charger la WSDL à partir du même serveur sécurisé () vous posera un problème de bootstrap, car la requête HTTPS pour rassembler la WSDL n'utilisera pas les mêmes informations d'identification que le service Web. J'ai contourné ce problème en rendant la WSDL disponible localement (fichier:///)...) et de changer dynamiquement le point final du service web: (une bonne discussion sur pourquoi cela est nécessaire peut être trouvé dans ce forum )
bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, webServiceLocation);
maintenant le WebService est bootstrapped et est capable de communiquer via SSL avec la contrepartie du serveur en utilisant un Client-Certificat nommé (alias) et une authentification mutuelle. ∎
C'est comment je l'ai résolu basé sur ce post avec quelques modifications mineures. Cette solution ne nécessite pas la création de classes supplémentaires.
SSLContext sc = SSLContext.getInstance("SSLv3");
KeyManagerFactory kmf =
KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() );
KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType() );
ks.load(new FileInputStream( certPath ), certPasswd.toCharArray() );
kmf.init( ks, certPasswd.toCharArray() );
sc.init( kmf.getKeyManagers(), null, null );
((BindingProvider) webservicePort).getRequestContext()
.put(
"com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory",
sc.getSocketFactory() );
j'ai essayé ce qui suit et cela n'a pas fonctionné sur mon environnement:
bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", getCustomSocketFactory());
mais la propriété différente a fonctionné comme un charme:
bindingProvider.getRequestContext().put(JAXWSProperties.SSL_SOCKET_FACTORY, getCustomSocketFactory());
le reste du code est tiré de la première réponse.
en combinant les réponses de Radek et de l0co vous pouvez accéder à la WSDL derrière https:
SSLContext sc = SSLContext.getInstance("TLS");
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(getClass().getResourceAsStream(keystore),
password.toCharArray());
kmf.init(ks, password.toCharArray());
sc.init(kmf.getKeyManagers(), null, null);
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
yourService = new YourService(url); //Handshake should succeed
ci-dessus est très bien (comme je l'ai dit en commentaire), à moins que votre WSDL est accessible à l'adresse https://.
Voici mon contournement pour ceci:
définit SSLSocketFactory par défaut:
HttpsURLConnection.setDefaultSSLSocketFactory(...);
pour Apache CXF que j'utilise, Vous devez aussi ajouter ces lignes à votre configuration:
<http-conf:conduit name="*.http-conduit">
<http-conf:tlsClientParameters useHttpsURLConnectionDefaultSslSocketFactory="true" />
<http-conf:conduit>
pour ceux qui essayent et ne parviennent toujours pas à le faire fonctionner, cela l'a fait pour moi avec Wildfly 8, en utilisant la dynamique Dispatcher
:
bindingProvider.getRequestContext().put("com.sun.xml.ws.transport.https.client.SSLSocketFactory", yourSslSocketFactory);
notez que la partie internal
de la clé de propriété est partie ici.
j'ai eu des problèmes de confiance en un certificat auto signé lors de la mise en place du gestionnaire de confiance. J'ai utilisé le constructeur SSLContexts d'apache httpclient pour créer un custom SSLSocketFactory
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStoreFile, "keystorePassword.toCharArray(), keyPassword.toCharArray())
.loadTrustMaterial(trustStoreFile, "password".toCharArray(), new TrustSelfSignedStrategy())
.build();
SSLSocketFactory customSslFactory = sslcontext.getSocketFactory()
bindingProvider.getRequestContext().put(JAXWSProperties.SSL_SOCKET_FACTORY, customSslFactory);
et passant dans le new TrustSelfSignedStrategy()
comme un argument dans la méthode loadTrustMaterial
.
j'ai essayé les pas ici:
http://jyotirbhandari.blogspot.com/2011/09/java-error-invalidalgorithmparameterexc.html
et, cela a réglé le problème. J'ai fait quelques modifications mineures - j'ai réglé les deux paramètres en utilisant le système.getProperty...