使用带有OkHttp的安全websockets(wss)

时间:2017-10-25 11:48:59

标签: android ssl websocket okhttp okhttp3

我尝试使用OkHttp3连接到安全的websocket服务器。当使用wss://echo.websocket.org它工作正常,没问题,但是当连接到正在进行的项目的生产服务器时,我没有正确连接到它。 30-40秒后onClosing调用WebSocketListener

我怀疑这与wss中的SSL / TLS加密有关。有没有办法让OkHttpClient接受新证书?

这是我现在用来与OkHttp3建立websocket连接的代码。

WebSocket webSocket;
OkHttpClient client;

OkHttpClient.Builder builder = new OkHttpClient.Builder();
client = builder.build();
Request request = new Request.Builder()
        .url(MainActivity.WS_URL)
        .header("Auth-Token","secret-api-token-here")
        .build();
Log.i("WebSockets", "Headers: " + request.headers().toString());
webSocket = client.newWebSocket(request, new WebSocketListener() {

    private static final int NORMAL_CLOSURE_STATUS = 1000;
    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        webSocket.send("{Auth-Token:secret-api-token-here}");
        Log.i("WebSockets", "Connection accepted!");
        //webSocket.close(NORMAL_CLOSURE_STATUS, "Goodbye !");
    }
    @Override
    public void onMessage(WebSocket webSocket, String text) {
        Log.i("WebSockets", "Receiving : " + text);
    }
    @Override
    public void onMessage(WebSocket webSocket, ByteString bytes) {
        Log.i("WebSockets", "Receiving bytes : " + bytes.hex());
    }
    @Override
    public void onClosing(WebSocket webSocket, int code, String reason) {
        webSocket.close(NORMAL_CLOSURE_STATUS, null);
        Log.i("WebSockets", "Closing : " + code + " / " + reason);
    }
    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        Log.i("WebSockets", "Error : " + t.getMessage());
    }});
}

2 个答案:

答案 0 :(得分:0)

我使用OkHttp3 websocket通过加密连接wss与服务器连接,我遇到了同样的问题。后来发现服务器在一段时间后关闭了连接。

答案 1 :(得分:-1)

由于这是我的Google搜索的第一个页面,因此我添加了对我有帮助的内容:

对于服务器端身份验证,服务器需要在受Android信任的证书上运行。因此,您(或您的后端同事)需要从官方CA获得一名。在Android手机设置下可以找到Android信任的证书颁发机构。对于我的Samsung S9,它位于生物特征和安全-其他安全设置-查看安全证书

为了通过 wss 连接到我的服务器,我还需要执行客户端身份验证。为此,您需要设置套接字工厂和信任管理器(还用于安全的HTTPS连接,而不仅仅是wss)。如果未设置,则将使用系统默认值,这意味着您没有服务器的正确套接字工厂,并且无法进行客户端身份验证。 代码示例:

        //Get TLS Manager for client-side TLS authentication
    String tlsKeyAlias = Prefs.getInstance(this).getCSKeyAlias();//get client signature keypair alias
    TLSManager tlsManager = new TLSManager(tlsKeyAlias); 

    //Create new https/wss client
    okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(2, TimeUnit.MINUTES)
            .writeTimeout(2, TimeUnit.MINUTES)
            .readTimeout(2, TimeUnit.MINUTES)
            .sslSocketFactory(tlsManager.getSSLSocketFactory(), tlsManager.getX509TrustManager())
            .build();

启动新的websocket时,您当然需要在URL中使用wss,我使用示例端口445:

    Request request = new Request.Builder()
        .url("wss://server.url.to.use:445/ExampleServiceProvider/endpoint")
        .build();//"wss://echo.websocket.org" - is available via default set

    WebSocketListener webSocketListener = new WebSocketListener();
    WebSocket ws = okHttpClient.newWebSocket(request, webSocketListener); 
    okHttpClient.dispatcher().executorService().shutdown();

其他信息: TLSManager类是我自己的类,我使用它来建立SSL套接字工厂以进行客户端身份验证,以便与服务提供商(Web App)进行通信。