Closed sristi closed 7 years ago
Do you receive a framing exception after the initial connect? Does your socket open if you trust all certificates? Not recommending to deploy a trust all solution to production, but it may help identifying the issue.
No Framing Exception. No, there is no possibility to connect to server without presenting client's certificate(Two-way SSL). However, Socket gets connected (and works OK) in Server Authentication (One-way SSL).
I tried with Chrome, always getting "WebSocket connection to 'wss://localhost:8887/' failed: WebSocket opening handshake timed out" error
@hellochenwang, which type of authentication are you using -- server-authentication or client-authentication ? I have worked with both type of authentication and there is no problem.
BTW, the problem we are discussing is getting connected from Android WSS:// clients.
@sristi I'm using server-authentication. Basically just like accessing https from chrome, in my case i'm trying to access wss from chrome. Did you modify the code to get it work?
So you are doing two way authentication(client verifies server's identity and server also verifies client's) with browser as the client? If this works, one way should work too.
In the example folder, there's a SSLClientExample.java and SSLServerExample.java. They work in paris, but SSLServerExample doesn't work with browsers.
@hellochenwang, No modification in this library code (if you had asked about it) has been done. For server-authentication, wss connection from Chrome client just works fine.
I've not used SSLServerExample from this library. For server-side sockets, I've used JEE7 libraries. I've been using this (Java-WebSocket) library only for connection from Android app to my JEE7 web application server.
For testing ws/wss websockets, I'm using chrome's extension called 'Simple WebSocket Client 0.1.3' (you might be already using it & also available for FireFox too).
@sristi, have you been able to use client certificates with this library?
Hello @sristi and others,
could you please try to build your jar directly from the sources? I merged some pull requests fixing bugs with wss!
Greetings marci4
Hello @marci4, I built the jar from source code with maven. The jar looks ok. I attempted to use it in android app for WSS connection with (Self-signed)client-certificate, and it was working Ok.
Cheers!
Hello @sristi,
please don't use maven right now. We haven't pushed an update to this repository yet! So there are propably not all relevant changes included.
(If you are unable to build the jar directly, fell free to ask)
Greetings marci4
Hello @marci4, Actually I built jar from the source cloned from github (and built jar using mvn clean install from CLI) not from maven central. I think you got misled by my last comment. Sorry for that.
Greetings,
Ahhh ok. Sorry for that then. (English is not my first language :( )
Could you provide some code for future developers? If it is fine for you I would add it to the wiki.
Greetings Marci4
Hello @marci4, Here I'm posting my dummy activity code that uses the java_websocket library to make WSS connection with client certificate authentication. Though the source is very rough, but the code is functional, at least it fulfills the required functionality for demo. I have tested the functionality on android API level 10 to 25, and it works OK. So, here we go.
This is the layout code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.syntech.websockettester.SecureWebsocketActivity"
android:orientation="vertical">
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:id="@+id/btnTestWss"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="WSS"
android:layout_weight="4"/>
</LinearLayout>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/websocketResponse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="kkk"
android:scrollbars="vertical"/>
</LinearLayout>
</LinearLayout>
And this is the Activity code:
package com.sristi.websockettester;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyStore;
import java.util.List;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.handshake.ServerHandshake;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/**
* @author sristi
*
* This is dummy activity to implement java_websocket library [ref. https://github.com/TooTallNate/Java-WebSocket.git]
* in android platforms.
*
* Secure websocket connection with client certificate has been implemented in this activity.
* Functionality of this activity has been tested from android platforms 2.3.3 [API level 10] to 7.1.1[API level 25]
* and works OK in all API levels.
* NOTE: R.raw.ca is my application's truststore in BKS format [I've placed the file in raw folder]
* R.raw.keystore is my application's client certificate in P12 format [I've placed the file in raw folder]
* webServiceUri is my server's websocket end point URL
*/
public class SecureWebsocketActivity extends Activity {
private static final String tag = "WEBSOCKET_ACTIVITY";
private static WebSocketClient webSocketClient;
private String webServiceUri = "wss://107.233.47.33:8443/mywebservice/services/";
TextView websocketResponse;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button btnOpenSecureWebSocket = (Button)findViewById(R.id.btnTestWss);
websocketResponse = (TextView)findViewById(R.id.websocketResponse);
websocketResponse.setMovementMethod(new ScrollingMovementMethod());
btnOpenSecureWebSocket.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
connectWebSocket();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressLint("TrulyRandom")
private void connectWebSocket() {
try {
URI uri = new URI(webServiceUri);
webSocketClient = new WebSocketClient(uri, new Draft_17()) {
@Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i(tag, "SOCKET OPENED");
}
@SuppressLint("NewApi")
@Override
public void onMessage(final String message) {
Log.i(tag, "Message from server is:" + message);
runOnUiThread(new Runnable() {
@Override
public void run() {
updateUi(message);
}
});
}
@Override
public void onClose(int i, final String s, boolean b) {
if (webSocketClient == null) {
connectWebSocket();
}
logEvent("Websocket", "Closed " + s);
}
@Override
public void onError(Exception e) {
logEvent("Websocket", "Error " + e.getMessage());
}
};
//Connect the secure websoket now
if(null!=webSocketClient && !webSocketClient.isOpen())
{
try {
if (webServiceUri.startsWith("wss")){
logEvent("SELF-Signed Conn",
"Trying wss conn with Self-Signed Certificate...");
webSocketClient.setSocket(getSslSocketFactory().createSocket());
webSocketClient.connect();
}
} catch (Exception e2) {
logEvent("WebSocket Unreachable", e2.getMessage());
}
}
} catch (URISyntaxException e) {
logEvent("WebSocket got some exception:", e.getMessage());
return;
}
}
private void logEvent(String title, String eventMessage) {
Log.i(title, eventMessage);
}
/**
* @param myPackage
* @return
*/
public boolean isApplicationGuiActive(String myPackage) {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTaskInfo = manager
.getRunningTasks(1);
ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
return componentInfo.getPackageName().equals(myPackage);
}
private SSLSocketFactory getSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore truststore = KeyStore.getInstance("BKS");
KeyStore keystore = KeyStore.getInstance("PKCS12");
String keystorePass = "MY_CLIENT_CERTIFICATE_PASS";
String truststorePass = "MY_CLIENT_TRUSTSTORE_PASS";
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream truststoreBksStream = getResources().openRawResource(R.raw.ca);
InputStream keystoreStream = getResources().openRawResource(R.raw.keystore);
try {
// Initialize the keystore with the provided trusted certificates
truststore.load(truststoreBksStream, truststorePass.toCharArray());
keystore.load(keystoreStream, keystorePass.toCharArray());
} finally {
truststoreBksStream.close();
keystoreStream.close();
}
SSLSocketFactory sf = new SSLSocketFactory(keystore, keystorePass, truststore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
private void updateUi(String currentMessage)
{
String oldMessage = websocketResponse.getText().toString();
websocketResponse.setText(oldMessage+"\n"+currentMessage);
}
}
And this one is Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sristi.websockettester"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".SecureWebsocketActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
cheers!
OMG! the automatic formats here resulted awful to my codes!
Hello @sristi
thx for your example!
(btw fixed the formatting for you :) )
Greetings marci4
I tried to implement WSS connection using SSLContext created from client certificate and CA certificate just like we do in plain java/JEE. But after the connection attempt, the socket is never opened.