I am creating an Android App which I want to connect to my server running secure websockets (wss). My code to connect is as below:
private void createWebSocketClient() {
URI uri;
try {
// Connect to local host
uri = new URI("wss://mysocketsdomain:8080/ws");
}
catch (URISyntaxException e) {
Log.d("Connection", "I am not even connecting");
e.printStackTrace();
return;
}
webSocketClient = new WebSocketClient(uri) {
#Override
public void onOpen() {
Log.i("WebSocket", "Session is starting");
webSocketClient.send("Hello World!");
}
#Override
public void onTextReceived(String s) {
Log.i("WebSocket", "Message received");
final String message = s;
runOnUiThread(new Runnable() {
#Override
public void run() {
try{
//TextView textView = findViewById(R.id.mainText);
//textView.setText(message);
} catch (Exception e){
e.printStackTrace();
}
}
});
}
#Override
public void onBinaryReceived(byte[] data) {
}
#Override
public void onPingReceived(byte[] data) {
}
#Override
public void onPongReceived(byte[] data) {
}
#Override
public void onException(Exception e) {
System.out.println(e.getMessage());
}
#Override
public void onCloseReceived() {
Log.i("WebSocket", "Closed ");
System.out.println("onCloseReceived");
}
};
webSocketClient.setConnectTimeout(10000);
webSocketClient.setReadTimeout(60000);
webSocketClient.enableAutomaticReconnection(5000);
webSocketClient.connect();
}
I am getting the error below:
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
The connection works fine if I visit the web front end from a browser and I can see that the certificate is valid from the padlock symbol. Also, the frontend web app that I developed using Svelte in JavaScript works fine.
Can anyone advise what I need to do? I am reading a lot of confusing information online. Some things suggest that I need to create a trusted certificate store in the Android app. Another thing that I saw suggested it is a problem with the server certificate chain. I set the server to use the certificate file containing the chain, but the error still happens. I am not sure if it would be the server when it works for the JavaScript app and the web front end.
try upgrade WeSocketClient library:
implementation 'tech.gusavila92:java-android-websocket-client:1.2.0'
Related
I created a basic selfhosted SignalR server with the following code:
class Program
{
static void Main(string[] args)
{
// This will *ONLY* bind to localhost, if you want to bind to all addresses
// use http://*:8080 to bind to all addresses.
// See http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx
// for more information.
string url = "http://localhost:8080";
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
}
}
Which is taken from: https://learn.microsoft.com/en-us/aspnet/signalr/overview/deployment/tutorial-signalr-self-host and works with the Javascript client.
I am now trying to create a Java client and got the following code that is simply supposed to send a message to the server:
String host = "http://localhost:8080";
HubConnection connection = new HubConnection(host);
HubProxy proxy = connection.createHubProxy("MyHub");
connection.start();
try {
System.out.println("Sendng message...");
proxy.invoke( "Send", "Client", "Hello world!" ).get();
System.out.println("Message sent!");
} catch (InterruptedException e) {
System.out.println("err1");
// Handle ...
} catch (ExecutionException e) {
System.out.println("err2");
// Handle ...
}
The problem that im having is that the message is not received by the server, it seems like the code is stuck at the invoke call and doesn't print the Hello world! message. Does someone know what im doing wrong?
hubProxy.invoke("sendMessageByUser", Message, WebApiToken).done(new Action<Void>() {
#Override
public void run(Void aVoid) {
if (aVoid != null)
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyApplicationService.this, "Mesaj gönderildi", Toast.LENGTH_SHORT).show();
}
});
}
}).onError(new ErrorCallback() {
#Override
public void onError(final Throwable error) {
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyApplicationService.this.getApplicationContext(), "Bir hata oluştu" + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
});
I am trying to connect with secure websocket connection wss:// in android using org.java_websocket.client.WebSocketClient API, but unable to connect with https. However it is working fine with ws://.. Here is my code.
private void connect(String websocketEndPointUrl) throws Exception {
URI uri;
try {
websocketEndPointUrl="wss://echo.websocket.org:443";
Log.i(TAG, " WSURL: " + websocketEndPointUrl);
uri = new URI(websocketEndPointUrl);
} catch (URISyntaxException e) {
Log.e(TAG, e.getMessage());
return;
}
mWebSocketClient = new WebSocketClient(uri,new Draft_17()) {
#Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i("Websocket", "Opened");
}
#Override
public void onMessage(String s) {
//final String message =s;
}
#Override
public void onClose(int i, String s, boolean b) {
Log.i("Websocket", "Closed " + s);
}
#Override
public void onError(Exception e) {
Log.i("Websocket", "Error " + e.getMessage());
}
};
mWebSocketClient.connect();
}
i am using online test websocket url:
ws://echo.websocket.org (port 80) // working with that
wss://echo.websocket.org (port 443)
As per my observation there is no need of certificate required in my code. Can anyone suggest me what is a reason and how i can fix this.
Find a solution. I don't know why this is not a part of the documentation. You just need to set setWebSocketFactory after WebSocketClient initialization and before the .connect() method
mWebSocketClient = new WebSocketClient(uri,new Draft_17())
{
#Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i("Websocket", "Opened");
}
#Override
public void onMessage(String s) {
//final String message =s;
}
#Override
public void onClose(int i, String s, boolean b) {
Log.i("Websocket", "Closed " + s);
}
#Override
public void onError(Exception e) {
Log.i("Websocket", "Error " + e.getMessage());
}
};
if (websocketEndPointUrl.indexOf("wss") == 0)
{
try {
SSLContext sslContext = SSLContext.getDefault();
mWebSocketClient.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
mWebSocketClient.connect();
In my case, I need two thing to fix "Trust anchor for certification path not found" error when websocket connect():
HttpsURLConnection requests that particular wss host (but in https:// form) successfully at least once.
Then dosetWebSocketFactory() as mentioned in accepted answer. Which this extra method (plus new Draft_17()) only appeared in library version org.java-websocket:Java-WebSocket:1.3.0, not 1.4.0.
Note that don't test with allowAllSSL() like this answer do, which affect the two thing above not working.
I am trying to integrate GoogleDriveSDK
Here is my code
mGoogleClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(new ConnectionCallbacks()
{
#Override
public void onConnectionSuspended(int arg0) {
}
#Override
public void onConnected(Bundle bundle)
{
AccountManager am = AccountManager.get(AddAccountActivity.this);
am.getAuthToken(am.getAccounts()[0], "oauth2:" + DriveScopes.DRIVE, new Bundle(), AddAccountActivity.this,
new OnTokenAcquired(), null);
}
})
.addOnConnectionFailedListener(new OnConnectionFailedListener()
{
#Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
if (connectionResult.hasResolution())
{
try {
connectionResult.startResolutionForResult(AddAccountActivity.this, ACTIVITY_RESULT_GOOGLE);
} catch (IntentSender.SendIntentException e)
{}
}
else
GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), AddAccountActivity.this, 0).show();
}
})
.build();
mGoogleClient.connect();
private class OnTokenAcquired implements AccountManagerCallback<Bundle>
{
#Override
public void run(AccountManagerFuture<Bundle> result)
{
try {
final String token = result.getResult().getString(AccountManager.KEY_AUTHTOKEN);
Intent launch = (Intent)result.getResult().get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, 3025);
return; // Not sure why... I wrote it here for some reason. Might not actually be necessary.
}
} catch (OperationCanceledException e) {
// Handle it...
} catch (AuthenticatorException e) {
// Handle it...
} catch (IOException e) {
// Handle it...
}
}
}
Now the problem is,i am not sure how can i get RefreshToken from authToken and save it for later use.
Secondly how can i use this refreshtoken saved to initialise Drive?
Not sure how much this helps. But you can have a look at this code and see if it helps.
https://github.com/sDurgam/koszt/blob/master/sTestJSONTables/src/com/example/s_expensemanager/MainActivity.java
Google drive only returns a refresh token during the initial login exchanging the code for the OAuth token.
refresh_token (optional) This field is only present if access_type=offline is included in the authentication request. For details, see Refresh tokens.
See the Google API documentation. This talks about how to us http requests and not the java objects but I would think the objects could be used in the same manor.
I have a client-side java code running in my Android Activity using the Gottox/socket.io.-java-client implementation on Github. This is the client code that needs to simple connect to a server and receive messages from it from time to time. Please bear with me as I'm very new to this domain and might be understanding this completely wrong!
This is what my client code looks like right now:
package com.example.culami;
import io.socket.IOAcknowledge;
import io.socket.IOCallback;
import io.socket.SocketIO;
import io.socket.SocketIOException;
import org.json.JSONException;
import org.json.JSONObject;
public class AcknowledgeExample implements IOCallback {
private SocketIO socket;
int connectionEstablished;
/**
* #param args
*/
/*public static void main(String[] args) {
try {
new AcknowledgeExample();
} catch (Exception e) {
e.printStackTrace();
}
}*/
public AcknowledgeExample() throws Exception
{
connectionEstablished = 0;
socket = new SocketIO();
socket.connect("http://192.168.0.108:3000/", this);
//socket.connect("http://localhost:3000/", this);
// Sends a string to the server.
//socket.send("Hello Server");
// Sends a JSON object to the server.
//socket.send(new JSONObject().put("key", "value").put("key2", "another value"));
//socket.send("server says hello!");
// Emits an event to the server.
//socket.emit("event", "argument1", "argument2", 13.37);
}
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
connectionEstablished = 1;
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
}
The server side code I'm currently trying to work with is taken from Socket.io's getting started tutorial page and looks as under:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res)
{
//res.sendFile(__dirname + '/index.html');
res.send('<h1>Hello world</h1>');
});
io.on('connection', function(socket)
{
console.log('a user connected');
/*socket.on('chat message', function(msg)
{
io.emit('chat message', msg);
});*/
});
All I need is to figure out a way to make my client and server codes connect. The server side code needs to be java script as sends the client a string keyword/message from time to time. Any pointers/suggestions/fixes will be highly appreciated.
I need some help concerning UnboundID. I heard it was a great choice but I'm not really used to it.
So I need to make a LDAP listener. On this listener, i should be able to catch bind request (from a ldap browser for example). I wonder how to get the DN and the password. Here is my code for the LDAP listener:
public ResultCode CreateLdapServer () throws LDAPException {
CannedResponseRequestHandler requestHandler = new CannedResponseRequestHandler();
LDAPListenerConfig config =
new LDAPListenerConfig(4243, requestHandler);
try
{
config.setListenAddress(
InetAddress.getByName("localhost"));
}
catch (final Exception e)
{
System.err.println("Unable to create the listen server.");
return ResultCode.PARAM_ERROR;
}
listener = new LDAPListener(config);
try
{
listener.startListening();
System.out.println("Serveur is listening ...");
}
catch (final Exception e)
{
System.err.println("Unable to start listening.");
return ResultCode.LOCAL_ERROR;
}
return ResultCode.SUCCESS;
}
public static void main(String[] args) throws LDAPException {
MyConnection connect = new MyConnection();
connect.CreateLdapServer();
}
I read a lot of UnboundID documentation, but i can't find any simple example of what I need.
Also, i'm not really sure of the utility of CannedResponseRequestHandler. For what i need, is it enough ?
An other question: I'm not sure, but I have the feeling that my server is not listening OR i don't catch anything (when I connect with a ldap Browser, nothing happened). Any Idea / Suggestion ?
Thanks and have a nice day !
EDIT : Thanks to xhochy, I was able to catch the password and the username. As he said, I subclassed LDAPListenerRequestyHandler to override, first, newInstance then ProcessBindRequest. Here is the code (it's absolutely not perfect and it's still a beginning).
public class MyConnection {
private LDAPListener listener;
public MyConnection(){
}
public ResultCode CreateLdapServer() throws LDAPException {
MyLDAPListenerRequestHandler requestHandler = new MyLDAPListenerRequestHandler();
LDAPListenerConfig config =
new LDAPListenerConfig(4243, requestHandler);
try
{
config.setListenAddress(
InetAddress.getByName("localhost"));
}
catch (final Exception e)
{
System.err.println("Unable to create the listen server.");
return ResultCode.PARAM_ERROR;
}
listener = new LDAPListener(config);
try
{
listener.startListening();
System.out.println("Serveur is listening ...");
}
catch (IOException e)
{
System.err.println("Unable to start listening.");
return ResultCode.LOCAL_ERROR;
}
return ResultCode.SUCCESS;
}
public static void main(String[] args) throws LDAPException {
MyConnection connect = new MyConnection();
connect.CreateLdapServer();
}
}
Then the subclass of LDAPListenerRequestHandler:
public class MyLDAPListenerRequestHandler extends LDAPListenerRequestHandler {
#Override
public LDAPListenerRequestHandler newInstance(
LDAPListenerClientConnection arg0) throws LDAPException {
System.out.println("New Instance.");
LDAPConnectionOptions option = new LDAPConnectionOptions();
LDAPConnection connection = new LDAPConnection(option, "yourIPadress", yourport);
System.out.println("Connected to : " + connection.getConnectedAddress()+ " " + connection.getConnectedPort());
return this;
}
#Override
public LDAPMessage processBindRequest(int arg0, BindRequestProtocolOp arg1,
List<Control> arg2) {
System.out.println(arg1.getBindDN());
System.out.println(arg1.getSimplePassword());
return null;
}
}
Thanks again !
Many LDAP server implementations will not return a password and many will not return a password you can use. (ie it maybe a hash).
I would be very curious why there could be a reason to return the password.
-jim
You should subclass LDAPListenerRequestHandler and implement processBindRequest. All the information you are looking for is included in BindRequestProtocolOp (second argument of processBindRequest). Add an empty implementation for all other abstract methods.
If request is your BindRequestProtocolOp instance then you get your information via:
String username = request.getBindDN();
ByteString password = request.getSimplePassword();