B4J Tutorial [Server] SSL Connections

Status
Not open for further replies.
Starting from B4J v2.00 the server can listen to two ports, the standard insecure port (http) and a secure port (https).

The default port for http is 80 and for https is 443. These ports are used when the url doesn't explicitly specify a port number.

It is recommended to go over the Wikipedia article to learn more about HTTPS: http://en.wikipedia.org/wiki/HTTP_Secure

SSL connections require some configuration. First you need a keystore file that stores the public and private keys. You can either purchase a key from a certificate authority or create one yourself. In the later case the browser will show a warning as the certificate cannot be verified.

These instructions explain how to create a key: http://www.eclipse.org/jetty/docume...rating-key-pairs-and-certificates-JDK-keytool

The server configuration is done with SslConfiguration object. This code should be called before the server is stared.
B4X:
Private Sub ConfigureSSL (SslPort As Int)
   'example of SSL connector configuration
   Dim ssl As SslConfiguration
   ssl.Initialize
   ssl.SetKeyStorePath(File.DirApp, "test2.keystore") 'path to keystore file
   ssl.KeyStorePassword = "123456"
   ssl.KeyManagerPassword = "654321"
   srvr.SetSslConfiguration(ssl, SslPort)
   'add filter to redirect all traffic from http to https (optional)
   srvr.AddFilter("/*", "HttpsFilter", False)
End Sub
We need to create a SslConfiguration object and set the path and passwords of the keystore file.
Then we call Server.SetSslConfiguration with the configuration object and the https port we want to listen to.


We can use a Filter class to redirect all http traffic to https:
B4X:
'Return True to allow the request to proceed.
Public Sub Filter(req As ServletRequest, resp As ServletResponse) As Boolean
   If req.Secure Then
     Return True
   Else
     resp.SendRedirect(req.FullRequestURI.Replace("http:", "https:") _
       .Replace(Main.srvr.Port, Main.srvr.SslPort))
     Return False
   End If
End Sub
This code checks whether the request is a secure request. If not it redirects the request to the https port and sets the scheme to https.

Note that trying to connect with http to the https port or with https to the http port will result with an error.

Filters do not apply to web sockets. You can use WebSocket.Secure to make sure that a secure connection has been made (this will be the case if the current request is a https request, unless someone has tampered the JavaScript code).
 
Last edited:

Fabrice La

Active Member
Licensed User
Longtime User
Hi Erel,

without ssl everything work good.
Program started.
repertoire: D:\JAVA4B~1\VERSIO~1\Objects\.ndf
2014-05-17 14:42:59.389:INFO::main: Logging initialized @733ms
JdbcUrl: jdbc:mysql://192.168.52.130:49500/ndf?characterEncoding=utf8
mai 17, 2014 2:42:59 PM com.mchange.v2.log.MLog <clinit>
Infos: MLog clients using java 1.4+ standard logging.
mai 17, 2014 2:42:59 PM com.mchange.v2.c3p0.C3P0Registry banner
Infos: Initializing c3p0-0.9.2.1 [built 20-March-2013 11:16:28 +0000; debug? true; trace: 10]
mai 17, 2014 2:42:59 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
Infos: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 20000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hgeb8l922tyaiv10z2awi|57c70722, debugUnreturnedConnectionStackTraces -> false, description ...
2014-05-17 14:43:00.191:INFO:eek:ejs.Server:main: jetty-9.1.z-SNAPSHOT
2014-05-17 14:43:00.228:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/mime, locale fr_FR
2014-05-17 14:43:00.230:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/encoding, locale fr_FR
2014-05-17 14:43:00.270:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@3ab770c0{/,file:/D:/Java4Basic/VersionWeb/Objects/www/,AVAILABLE}
2014-05-17 14:43:00.272:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened D:\Java4Basic\VersionWeb\Objects\logs\b4j-2014_05_17.request.log
2014-05-17 14:43:00.286:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@325a2045{HTTP/1.1}{0.0.0.0:52084}
2014-05-17 14:43:00.287:INFO:eek:ejs.Server:main: Started @1653ms
Emulated network latency: 200ms
Server started
But if I try to use ssl connection, not error message:
Program started.
repertoire: D:\JAVA4B~1\VERSIO~1\Objects\.ndf
2014-05-17 14:37:57.734:INFO::main: Logging initialized @708ms
JdbcUrl: jdbc:mysql://192.168.52.130:49500/ndf?characterEncoding=utf8
mai 17, 2014 2:37:57 PM com.mchange.v2.log.MLog <clinit>
Infos: MLog clients using java 1.4+ standard logging.
mai 17, 2014 2:37:58 PM com.mchange.v2.c3p0.C3P0Registry banner
Infos: Initializing c3p0-0.9.2.1 [built 20-March-2013 11:16:28 +0000; debug? true; trace: 10]
mai 17, 2014 2:37:58 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
Infos: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 20000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hgeb8l922trtql1m0pipe|6b95d875, debugUnreturnedConnectionStackTraces -> false, description ...
2014-05-17 14:37:58.508:INFO:eek:ejs.Server:main: jetty-9.1.z-SNAPSHOT
2014-05-17 14:37:58.534:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/mime, locale fr_FR
2014-05-17 14:37:58.536:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/encoding, locale fr_FR
2014-05-17 14:37:58.568:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@34d26e27{/,file:/D:/Java4Basic/VersionWeb/Objects/www/,AVAILABLE}
2014-05-17 14:37:58.570:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened D:\Java4Basic\VersionWeb\Objects\logs\b4j-2014_05_17.request.log
2014-05-17 14:37:58.584:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@38942215{HTTP/1.1}{0.0.0.0:52084}
2014-05-17 14:37:58.678:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@70f91e8{SSL-http/1.1}{0.0.0.0:52088}
2014-05-17 14:37:58.678:INFO:eek:ejs.Server:main: Started @1673ms
Emulated network latency: 200ms
Server started

I f I use the url http://http://192.168.52.101:52084/ The browser goes to https://192.168.52.101:52088/ and says the connection has been stopped
 

Fabrice La

Active Member
Licensed User
Longtime User
Yes I saw that when you try http it redirect to https

I used keytool
And if I used "keystore Explorer" I can read certificat

But in https nothing works ...
 

LucaMs

Expert
Licensed User
Longtime User
I'm tired. Surely!

First you need a keystore file that stores the public and private keys.

Keys: in your example you used only a pair for the keystore or i'm wrong?

Then can I use the keys stored in the keystore to allow access to some entity (person, app, ...)? How? Adding other filters and checking...?

From italian Wikipedia - HTTPS:
Questa tecnologia quindi può essere usata anche per permettere un accesso limitato ad un web server. L'amministratore spesso crea dei certificati per ogni utente che vengono caricati nei loro browser contenenti informazioni come il relativo nome e indirizzo e-mail in modo tale da permettere al server di riconoscere l'utente nel momento in cui quest'ultimo tenti di riconnettersi senza immettere nome utente e/o password.
---
This technology can therefore be used also to allow a limited access to a web server. The administrator often creates certificates for each user that are loaded in their browsers contain information such as a name and email address in such a way as to allow the server to recognize the user when he tries to reconnect without enter his username and/or password.
---


Altruist suggestion: the best answer would be to edit the project attached to this post. :D


[P.S. Perhaps, for my example, the password for accessing CCTV, SslConfiguration object and the filter are sufficient (ie the transfer of pw between the browser and the server becomes safe) and the other keys are used for other "individual controls".
Let's try.]
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Generating Keys and Certificates with JDK keytool

This command prompts for information about the certificate and for passwords to protect both the keystore and the keys within it. The only mandatory response is to provide the fully qualified host name of the server at the "first and last name" prompt.

My fully qualified host name of the server actually can be only "localhost" or my pc's ip address :eek: I hope that it will be accepted.
 

LucaMs

Expert
Licensed User
Longtime User
ssl.KeyManagerPassword = "654321" ???

I ran the command as the page of the link:
These instructions explain how to create a key: http://wiki.eclipse.org/Jetty/Howto/Configure_SSL#Generating_Keys_and_Certificates_with_JDK_keytool

keytool -keystore NameOfMyKeystore.keystore -alias jetty -genkey -keyalg RSA

executing: keytool -keystore NameOfMyKeystore.keystore -list
I get the jetty's key/value.

KeyManagerPassword???


[P.S. I have tried to use the jetty's pw for KeyManagerPassword and SEEMS to work]
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
B4X:
'Return True to allow the request to proceed.
Public Sub Filter(req As ServletRequest, resp As ServletResponse) As Boolean
  If req.Secure Then
    Return True
  Else
    resp.SendRedirect(req.FullRequestURI.Replace("http:", "https:") _
      .Replace(Main.srvr.Port, Main.srvr.SslPort))
    Return False
  End If
End Sub

It can't be compiled, because Main.srvr is declared as Private. I change it to Public, hoping that this is not a problem.


[P.S. create two public variables for the two ports is a better choice:
B4X:
resp.SendRedirect(req.FullRequestURI.Replace("http:", "https:") _
      .Replace(Main.ServerPort, Main.ServerSSLPort))

]
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Why is it better???
I thought I was weird avoid interventions on a server spread across other handlers.


To me is not clear the use of SSLConfiguration, the keystore and the filter.

I have tried to use the filter by matching it to a subfolder but it seems that it only works with "/ *" (but I may have gotten lost, surely).

Again with reference to CCTV (but only as an example) I would only use HTTPS to login. The redirection occurs but then the other handlers are not executed.

Should we use the entries in the keystore for user credentials?

Questa tecnologia quindi può essere usata anche per permettere un accesso limitato ad un web server. L'amministratore spesso crea dei certificati per ogni utente che vengono caricati nei loro browser contenenti informazioni come il relativo nome e indirizzo e-mail in modo tale da permettere al server di riconoscere l'utente nel momento in cui quest'ultimo tenti di riconnettersi senza immettere nome utente e/o password.
 
Last edited:

dar2o3

Active Member
Licensed User
Longtime User
Hello, I try to operate the keys provided by let's encrypt .pem format but do not get any satisfactory result, somebody to get it?
 
Status
Not open for further replies.
Top