Comment programmer le contexte SSL D'un client JAX-WS?

interation et moi avons un certificat de client signé par le tiers.

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?

50
demandé sur Tshepang 2012-06-12 20:48:57

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. ∎

52
répondu maasg 2013-04-04 17:08:55

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() );
20
répondu Radek 2017-05-23 12:26:23

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.

17
répondu Igors Sakels 2012-10-30 13:47:54

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
3
répondu cidus 2015-07-24 21:44:40

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>
2
répondu Łukasz Frankowski 2013-10-25 10:46:08

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.

0
répondu Davio 2014-04-14 06:58:32

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 .

0
répondu user3047573 2017-06-12 21:00:35

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...

0
répondu Kumar Saurabh 2017-06-23 17:17:26