2015-03-21 17 views
6

Sto provando a connettermi a una websocket protetta usando Jetty (o qualsiasi altra libreria).Connessione a una presa Web protetta

Il problema è relativo all'errore "Nessun certificato attendibile trovato". Sto usando un certificato autofirmato generato con keytool. Cosa si potrebbe fare?

import java.net.URI; 
import java.util.concurrent.Future; 

import org.eclipse.jetty.util.resource.Resource; 
import org.eclipse.jetty.util.ssl.SslContextFactory; 
import org.eclipse.jetty.websocket.api.Session; 
import org.eclipse.jetty.websocket.api.WebSocketAdapter; 
import org.eclipse.jetty.websocket.client.WebSocketClient; 

public class Socket extends WebSocketAdapter{ 

    public static void main(String[] args) { 
     String url = "wss://qa.sockets.stackexchange.com/"; //or "wss://echo.websocket.org" 
     // making sure the the jvm find keystore 
     String JAVASEC="C:/Program Files/Java/jdk1.8.0_25/jre/lib/security/"; 
     System.setProperty("javax.net.ssl.keyStore", JAVASEC+"keystore.jks"); 
     System.setProperty("javax.net.ssl.trustStore", JAVASEC+"cacerts.jks"); 
     System.setProperty("javax.net.ssl.keyStorePassword", "changeit"); 

     System.out.println(System.getProperty("javax.net.ssl.trustStore")); 
     SslContextFactory sslContextFactory = new SslContextFactory(); 
     Resource keyStoreResource = Resource.newResource(Socket.class.getResource("/keystore.jks"));//generated with keytool 
     sslContextFactory.setKeyStoreResource(keyStoreResource); 
     sslContextFactory.setKeyStorePassword("password"); 
     sslContextFactory.setKeyManagerPassword("password"); 
     WebSocketClient client = new WebSocketClient(sslContextFactory); 
     try{ 
      client.start(); 
      Socket socket = new Socket(); 
      Future<Session> fut = client.connect(socket,URI.create(url)); 
      Session session = fut.get(); 
      session.getRemote().sendString("Hello"); 
     } 
     catch (Throwable t){ 
      t.printStackTrace(System.err); 
     } 
    } 


    @Override 
    public void onWebSocketConnect(Session sess){ 
     super.onWebSocketConnect(sess); 
     System.out.println("Socket Connected: " + sess); 
    } 

    @Override 
    public void onWebSocketText(String message){ 
     super.onWebSocketText(message); 
     System.out.println("Received TEXT message: " + message); 
    } 

    @Override 
    public void onWebSocketClose(int statusCode, String reason){ 
     super.onWebSocketClose(statusCode,reason); 
     System.out.println("Socket Closed: [" + statusCode + "] " + reason); 
    } 

    @Override 
    public void onWebSocketError(Throwable cause){ 
     super.onWebSocketError(cause); 
     cause.printStackTrace(System.err); 
    } 
} 

Ecco un tentativo con Tyrus cliente websocket, non ottengo l'errore SSL, ma non stampa:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.URI; 
import java.net.URISyntaxException; 

import javax.websocket.ClientEndpointConfig; 
import javax.websocket.CloseReason; 
import javax.websocket.DeploymentException; 
import javax.websocket.Endpoint; 
import javax.websocket.EndpointConfig; 
import javax.websocket.MessageHandler; 
import javax.websocket.Session; 

import org.glassfish.grizzly.ssl.SSLContextConfigurator; 
import org.glassfish.grizzly.ssl.SSLEngineConfigurator; 
import org.glassfish.tyrus.client.ClientManager; 
import org.glassfish.tyrus.container.grizzly.GrizzlyEngine; 

public class ClientWebSocketEndpoint extends Endpoint { 

    public static void main(String[] a) throws IOException{ 

     ClientManager client = ClientManager.createClient(); 

     //System.getProperties().put("javax.net.debug", "all"); 
     final SSLContextConfigurator defaultConfig = new SSLContextConfigurator(); 

     defaultConfig.retrieve(System.getProperties()); 
      // or setup SSLContextConfigurator using its API. 

     SSLEngineConfigurator sslEngineConfigurator = 
      new SSLEngineConfigurator(defaultConfig, true, false, false); 
     client.getProperties().put(GrizzlyEngine.SSL_ENGINE_CONFIGURATOR, 
      sslEngineConfigurator); 
     Session session = null; 
     final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build(); 

     try { 
      session = client.connectToServer(ClientWebSocketEndpoint.class, cec, new URI("wss://qa.sockets.stackexchange.com/"));// or "wss://echo.websocket.org" 

     } catch (DeploymentException | URISyntaxException e) { 
      e.printStackTrace(); 
     } finally { 
      if (session != null && session.isOpen()) 
       session.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "Bye")); 

     } 

     BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
     br.readLine(); 
    } 

    @Override 
    public void onOpen(Session session, EndpointConfig config) { 
     session.addMessageHandler(new MessageHandler.Whole<String>() { 

      @Override 
      public void onMessage(String message) { 
       System.out.println("Received message: "+message); 
      } 
     }); 
     try { 
      session.getBasicRemote().sendText("1-questions-active"); 
      session.getBasicRemote().sendText("155-questions-active"); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 
} 

In confronto questo semplice codice JS/nodo funziona

var WebSocket = require('ws') 
    , ws = new WebSocket('wss://qa.sockets.stackexchange.com/');//"wss://echo.websocket.org" 

ws.on('message', function(message) { 
    console.log('received: %s', message); 
}); 
ws.on('open', function() { 
    ws.send('155-questions-active'); 
    ws.send('1-questions-active'); 
}); 

Sarei felice di conoscere un client Websocket funzionante in Java

+0

possibile duplicato di [indicare java per accettare il certificato ssl autofirmato] (http://stackoverflow.com/questions/2893819/telling-java-to-accept-self-signed-ssl-certificate) – tinker

+0

@tinker I l'ho appena provato, sono andato su https://qa.sockets.stackexchange.com/ con un browser, ho esportato il certificato e l'ho importato in cacerts 'keytool -import ...', e ho eseguito di nuovo questo codice, ottenuto il stesso errore "Nessun certificato attendibile trovato" – caub

+0

Lo hai eseguito con un negozio sicuro e la password corretta? Assicurati che JVM stia utilizzando il trust store corretto – tinker

risposta

12

C'è un modo molto più semplice, non c'è bisogno di pasticciare con truststore, o custom X509TrustManagers, o su misura SSLContexts.

Proprio utilizzano quello che viene fornito con SslContextFactory già ...

package jetty.websocket; 

import java.net.URI; 
import java.util.concurrent.Future; 

import org.eclipse.jetty.util.log.Log; 
import org.eclipse.jetty.util.log.Logger; 
import org.eclipse.jetty.util.ssl.SslContextFactory; 
import org.eclipse.jetty.websocket.api.Session; 
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; 
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; 
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; 
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; 
import org.eclipse.jetty.websocket.api.annotations.WebSocket; 
import org.eclipse.jetty.websocket.client.WebSocketClient; 

@WebSocket 
public class SecureClientSocket 
{ 
    private static final Logger LOG = Log.getLogger(SecureClientSocket.class); 

    public static void main(String[] args) 
    { 
     String url = "wss://qa.sockets.stackexchange.com/"; 

     SslContextFactory sslContextFactory = new SslContextFactory(); 
     sslContextFactory.setTrustAll(true); // The magic 

     WebSocketClient client = new WebSocketClient(sslContextFactory); 
     try 
     { 
      client.start(); 
      SecureClientSocket socket = new SecureClientSocket(); 
      Future<Session> fut = client.connect(socket,URI.create(url)); 
      Session session = fut.get(); 
      session.getRemote().sendString("Hello"); 
      session.getRemote().sendString("155-questions-active"); 
     } 
     catch (Throwable t) 
     { 
      LOG.warn(t); 
     } 
    } 

    @OnWebSocketConnect 
    public void onConnect(Session sess) 
    { 
     LOG.info("onConnect({})",sess); 
    } 

    @OnWebSocketClose 
    public void onClose(int statusCode, String reason) 
    { 
     LOG.info("onClose({}, {})", statusCode, reason); 
    } 

    @OnWebSocketError 
    public void onError(Throwable cause) 
    { 
     LOG.warn(cause); 
    } 

    @OnWebSocketMessage 
    public void onMessage(String msg) 
    { 
     LOG.info("onMessage() - {}", msg); 
    } 
} 

che avrà risultati come questo ...

2015-03-26 06:46:34.893:INFO::main: Logging initialized @62ms 
2015-03-26 06:46:35.700:INFO:jw.SecureClientSocket:[email protected]: onConnect(WebSocketSession[websocket=JettyAnnotatedEventDriver[[email protected]],behavior=CLIENT,[email protected]{IDLE}{f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[CLIENT,validating],[email protected][ExtensionStack,s=START,c=0,len=0,f=null,[email protected][behavior=CLIENT,maxTextMessageSize=65536,maxTextMessageBufferSize=32768,maxBinaryMessageSize=65536,maxBinaryMessageBufferSize=32768,asyncWriteTimeout=60000,idleTimeout=300000,inputBufferSize=4096]]},[email protected][batching=true],incoming=JettyAnnotatedEventDriver[[email protected]],outgoing=ExtensionStack[queueSize=0,extensions=[],incoming=org.eclipse.jetty.websocket.common.WebSocketSession,outgoing=org.eclipse.jetty.websocket.client.io.WebSocketClientConnection]]) 
2015-03-26 06:46:39.464:INFO:jw.SecureClientSocket:[email protected]: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"math.stackexchange.com\",\"id\":1207542,\"titleEncodedFancy\":\"Do we have this type of integral expression of Bessel function of the first kind?\",\"bodySummary\":\"Let $z=\\\\lambda+i\\\\mu$ with $\\\\mu&gt;0$. Then for any $r&gt;0$, $k=1,2,3, \\\\cdots$. Do we have the following identity\\n$$\\n\\\\int_{r}^{\\\\infty}{\\\\frac{t}{\\\\sqrt{t^2-r^2}}(\\\\frac{1}{t}\\\\frac{d}{dt})^k ...\",\"tags\":[\"analysis\",\"reference-request\",\"special-functions\"],\"lastActivityDate\":1427377599,\"url\":\"http://math.stackexchange.com/questions/1207542/do-we-have-this-type-of-integral-expression-of-bessel-function-of-the-first-kind\",\"ownerUrl\":\"http://math.stackexchange.com/users/37742/sun\",\"ownerDisplayName\":\"sun\",\"apiSiteParameter\":\"math\"}"} 
2015-03-26 06:46:41.469:INFO:jw.SecureClientSocket:[email protected]: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"drupal.stackexchange.com\",\"id\":152924,\"titleEncodedFancy\":\"Features can export everything?\",\"bodySummary\":\"Built all blocks, menu, taxonomies, view etc in Drupal CMS on localhost machine, but I need to export everything to the live server. Is it possible to use features or just export sql?\\n\",\"tags\":[\"theming\"],\"lastActivityDate\":1427377601,\"url\":\"http://drupal.stackexchange.com/questions/152924/features-can-export-everything\",\"ownerUrl\":\"http://drupal.stackexchange.com/users/34551/joe\",\"ownerDisplayName\":\"joe\",\"apiSiteParameter\":\"drupal\"}"} 
2015-03-26 06:46:44.034:INFO:jw.SecureClientSocket:[email protected]: onMessage() - {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"wordpress.stackexchange.com\",\"id\":182350,\"titleEncodedFancy\":\"Create page from plugin, but have it completely hidden\",\"bodySummary\":\"I need to have a plugin create a page that is publicly accessible, but does NOT show up in the admin section anywhere, and cannot be deleted or modified.\\n\\nI thought maybe figuring out a way to have a ...\",\"tags\":[\"plugins\",\"pages\"],\"lastActivityDate\":1427377603,\"url\":\"http://wordpress.stackexchange.com/questions/182350/create-page-from-plugin-but-have-it-completely-hidden\",\"ownerUrl\":\"http://wordpress.stackexchange.com/users/45132/joel-worsham\",\"ownerDisplayName\":\"Joel Worsham\",\"apiSiteParameter\":\"wordpress\"}"} 
+0

Ho intenzione di testare il tuo codice. Grazie mille per questo! –

2

Bene, ho provato a utilizzare il codice per replicare il problema senza alcun risultato (ottenere il certificato, importarlo con il comando keytool e quindi eseguire il codice). la mia uscita è così.

2015-03-22 23:03:16.192:INFO::main: Logging initialized @503ms 
Socket Connected:WebSocketSession[websocket=JettyListenerEventDriver[com.ivan.Main],behavior=CLIENT,[email protected]{IDLE}{f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[CLIENT,validating],[email protected][ExtensionStack,s=START,c=0,len=0,f=null,[email protected][behavior=CLIENT,maxTextMessageSize=65536,maxTextMessageBufferSize=32768,maxBinaryMessageSize=65536,maxBinaryMessageBufferSize=32768,asyncWriteTimeout=60000,idleTimeout=300000,inputBufferSize=4096]]},[email protected][batching=true],incoming=JettyListenerEventDriver[com.ivan.Main],outgoing=ExtensionStack[queueSize=0,extensions=[],incoming=org.eclipse.jetty.websocket.common.WebSocketSession,outgoing=org.eclipse.jetty.websocket.client.io.WebSocketClientConnection]] 
Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"cogsci.stackexchange.com\",\"id\":9404,\"titleEncodedFancy\":\"What&#39;s the difference between repetition suppression and habituation?\",\"bodySummary\":\"Neural repetition suppression seems to be describing behavioral habituation on a neuronal level. What's the difference between these two terms?\\n\",\"tags\":[\"cognitive-neuroscience\",\"terminology\",\"conditioning\",\"perceptual-learning\"],\"lastActivityDate\":1427036607,\"url\":\"http://cogsci.stackexchange.com/questions/9404/whats-the-difference-between-repetition-suppression-and-habituation\",\"ownerUrl\":\"http://cogsci.stackexchange.com/users/7569/recursive-farts\",\"ownerDisplayName\":\"RECURSIVE FARTS\",\"apiSiteParameter\":\"cogsci\"}"} 
Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"mathematica.stackexchange.com\",\"id\":77933,\"titleEncodedFancy\":\"FunctionDomain doesn&#39;t work with If\",\"bodySummary\":\"When I call FunctionDomain for function defined by formule with If, for example \\n\\nf[x_]:=If[x&lt;0, x, x^3], \\n\\nI get \\\"Unable to find the domain with the available methods\\\". What should I do to get a ...\",\"tags\":[\"functions\"],\"lastActivityDate\":1427036609,\"url\":\"http://mathematica.stackexchange.com/questions/77933/functiondomain-doesnt-work-with-if\",\"ownerUrl\":\"http://mathematica.stackexchange.com/users/27150/adolzi\",\"ownerDisplayName\":\"adolzi\",\"apiSiteParameter\":\"mathematica\"}"} 
Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"serverfault.com\",\"id\":677390,\"titleEncodedFancy\":\"Smart Array E200i battery on 350ML did not fix the warning message (battery failure)\",\"bodySummary\":\"I have got this warning message on the System Management in a Proliant server 350ML G5.\\n\\nDegraded Accelerator\\nName Value\\nStatus: Temporarily Disabled\\nError Code: Cache Disabled Low Batteries\\nSerial ...\",\"tags\":[\"hp-proliant\",\"hp-smart-array\"],\"lastActivityDate\":1427036609,\"url\":\"http://serverfault.com/questions/677390/smart-array-e200i-battery-on-350ml-did-not-fix-the-warning-message-battery-fail\",\"ownerUrl\":\"http://serverfault.com/users/164557/dlopezgonzalez\",\"ownerDisplayName\":\"dlopezgonzalez\",\"apiSiteParameter\":\"serverfault\"}"} 
Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"askubuntu.com\",\"id\":599889,\"titleEncodedFancy\":\"Is downgrading back to 14.04 from 14.10 possible?\",\"bodySummary\":\"I am using Ubuntu 14.10 alongside Windows 7 and I want to degrade to 14.04. I made a bootable pendrive using Universal USB Installer and seems like the pendrive is working fine. On the Installer Boot ...\",\"tags\":[\"14.04\",\"boot\",\"upgrade\",\"downgrade\"],\"lastActivityDate\":1427036610,\"url\":\"http://askubuntu.com/questions/599889/is-downgrading-back-to-14-04-from-14-10-possible\",\"ownerUrl\":\"http://askubuntu.com/users/374332/pkj\",\"ownerDisplayName\":\"pkj\",\"apiSiteParameter\":\"askubuntu\"}"} 
Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"superuser.com\",\"id\":814765,\"titleEncodedFancy\":\"External Harddrive Shutting Off and On Every So Often While Listening to Music\",\"bodySummary\":\"I am always listening to music on my PC (always via VLC Player) and every so often - maybe once every 2 songs, sometimes more frequently- the music stops playing (VLC's buffer/progress bar stops ...\",\"tags\":[\"hard-drive\",\"power\",\"external\"],\"lastActivityDate\":1427036610,\"url\":\"http://superuser.com/questions/814765/external-harddrive-shutting-off-and-on-every-so-often-while-listening-to-music\",\"ownerUrl\":\"http://superuser.com/users/338547/supercookie47\",\"ownerDisplayName\":\"SuperCookie47\",\"apiSiteParameter\":\"superuser\"}"} 
Received TEXT message: {"action":"155-questions-active","data":"{\"siteBaseHostAddress\":\"math.stackexchange.com\",\"id\":1200778,\"titleEncodedFancy\":\"Continuity of a piecewise function at a specific point\",\"bodySummary\":\"I am having trouble proving the following function is not continuous at $x = 0$ using a formal definition of continuity.\\n\\n$\\nf(x) = \\\\left\\\\{\\n \\\\begin{array}{lr}\\n \\\\sin(\\\\frac{1}{x}) &amp; : x \\\\neq 0\\\\\\\\\\n ...\",\"tags\":[\"real-analysis\",\"functions\",\"continuity\",\"epsilon-delta\"],\"lastActivityDate\":1427036612,\"url\":\"http://math.stackexchange.com/questions/1200778/continuity-of-a-piecewise-function-at-a-specific-point\",\"ownerUrl\":\"http://math.stackexchange.com/users/222744/george\",\"ownerDisplayName\":\"George\",\"apiSiteParameter\":\"math\"}"} 

Quindi credo che, se si desidera un running web client socket in Java, penso che si potrebbe semplicemente accettare tutti i certificati come il link che @tinker ha dato a voi.

Il codice dovrebbe essere come questo. forse potresti provarlo e vedere cosa succede al tuo posto.

import java.net.URI; 
import java.security.cert.X509Certificate; 
import java.util.concurrent.Future; 

import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 

import org.eclipse.jetty.util.ssl.SslContextFactory; 
import org.eclipse.jetty.websocket.api.Session; 
import org.eclipse.jetty.websocket.api.WebSocketAdapter; 
import org.eclipse.jetty.websocket.client.WebSocketClient; 

public class Main extends WebSocketAdapter { 

    public static void main(String[] args) { 
    String url = "wss://qa.sockets.stackexchange.com/"; // or 
          // "wss://echo.websocket.org" 
SslContextFactory sslContextFactory = new SslContextFactory(); 
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { 
    public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
    return new X509Certificate[0]; 
    } 

    public void checkClientTrusted(
     java.security.cert.X509Certificate[] certs, String authType) { 
    } 

    public void checkServerTrusted(
     java.security.cert.X509Certificate[] certs, String authType) { 
    } 
} }; 
try { 
    SSLContext sc = SSLContext.getInstance("SSL"); 
    sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
    sslContextFactory.setSslContext(sc); 
    WebSocketClient client = new WebSocketClient(sslContextFactory); 

    client.start(); 
    Future<Session> fut = client.connect(new Main(), URI.create(url)); 
    Session session = fut.get(); 
    session.getRemote().sendString("Hello"); 
    session.getRemote().sendString("155-questions-active"); 
} catch (Throwable t) { 
    t.printStackTrace(System.err); 
} 
} 

@Override 
public void onWebSocketConnect(Session sess) { 
super.onWebSocketConnect(sess); 
System.out.println("Socket Connected: " + sess); 
} 

@Override 
public void onWebSocketText(String message) { 
super.onWebSocketText(message); 
System.out.println("Received TEXT message: " + message); 
} 

@Override 
public void onWebSocketClose(int statusCode, String reason) { 
super.onWebSocketClose(statusCode, reason); 
System.out.println("Socket Closed: [" + statusCode + "] " + reason); 
} 

@Override 
public void onWebSocketError(Throwable cause) { 
super.onWebSocketError(cause); 
cause.printStackTrace(System.err); 
} 
} 
+0

congratulazioni, come hai fatto a capire? – caub

+0

beh, nella mia esperienza passata, ho avuto questo tipo di problema nel mio lavoro, comunque felice potrebbe essere d'aiuto;) –

1

Ecco il mio cliente Tyrus-java utilizzando stub che ho usato per la connessione al mio server Jetty 9.3.6 che esegue HTTPS con un certificato autofirmato (adattato da Tyrus websocket client, Sezione 8.1):

  client = ClientManager.createClient(); 

      //System.getProperties().put("javax.net.debug", "all"); // Useful for debugging SSL interaction 
      // The keystore in the next two lines is the same keystore you used for running the server, 
      // likely in ${jetty.base}/etc/keystore 
      System.getProperties().put(SSLContextConfigurator.KEY_STORE_FILE, "/tmp/keystore"); 
      System.getProperties().put(SSLContextConfigurator.TRUST_STORE_FILE, "/tmp/keystore"); 
      // The following two passwords are what you used for your self-signed cert 
      System.getProperties().put(SSLContextConfigurator.KEY_STORE_PASSWORD, "HumanReadablePassword"); 
      System.getProperties().put(SSLContextConfigurator.TRUST_STORE_PASSWORD, "HumanReadablePassword"); 
      final SSLContextConfigurator defaultConfig = new SSLContextConfigurator(); 

      defaultConfig.retrieve(System.getProperties()); 
      // or setup SSLContextConfigurator using its API. 

      SSLEngineConfigurator sslEngineConfigurator = new SSLEngineConfigurator(defaultConfig, true, false, false); 
      client.getProperties().put(GrizzlyEngine.SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator); 
      client.connectToServer(sillyWebSocketClient , ClientEndpointConfig.Builder.create().build(), 
            new URI("wss://localhost:8443/sillyWebSocketServer/echo")); 
      System.out.println ("Connected .... "); 

Dove SillyWebSocketClient sillyWebSocketClient si estende javax.websocket.Endpoint.

Sto usando un/Gradle 2,7 ambiente Java 8, e la mia build.gradle si presenta così:

apply plugin: 'java' 

repositories { 
    mavenCentral() 
} 

dependencies { 
     compile 'javax:javaee-api:7.0' 
     compile 'org.glassfish.grizzly:grizzly-core:2.3.23' 
     compile 'org.glassfish.tyrus:tyrus-container-grizzly:1.2.1' 
     compile 'org.glassfish.tyrus:tyrus-client:1.6' 
     compile 'javax.websocket:javax.websocket-client-api:1.1' 
} 

Spero che questo aiuti.

Problemi correlati