Try it online: https://www.b4x.com:51042/login_example/
Note that it is not connected to the forum database. Feel free to test it and register new users. Its only purpose is to demonstrate this solution.
A typical web solution consists of several folders. In this case the structure is:
We want to restrict access to files and handlers under the 'members' folder to registered members only.
This is done with a Filter.
Each request is handled by a single handler or if no handler matches the URL then a file is returned (or 404 error if there is no matching file).
Filters are similar to handlers. However the request can go through any number of filters before it reaches its final destination. Filters can change the request destination or block the request.
A Filter class should include a sub named Filter with the following signature:
Public Sub Filter(req As ServletRequest, resp As ServletResponse) As Boolean
Adding filters is done with Server.AddFilter. In our example we want to apply the filter to all files and handlers under the 'members' folder (notice the wildcard in the path):
srvr.AddFilter("/login_example/members/*", "MembersFilter", False)
The filter code:
Public Sub Filter(req As ServletRequest, resp As ServletResponse) As Boolean If req.GetSession.GetAttribute2("registered", "") = True Then 'check that no more than 30 minutes passed since last activity If req.GetSession.LastAccessedTime + DateTime.TicksPerMinute * 30 > DateTime.Now Then Return True 'allow request to continue End If End If resp.SendRedirect("/login_example/") Return False End Sub
This attribute is set when the user registers to the forum or signs in. Remember that user sessions are stored in the server memory. This means that they are safe to use (a cookie will not work here). However this also means that the user will need to sign in again (no need to register again) if the server is restarted.
When a user registers we need to save it in the database. For security reasons we do not save the password. Instead we save a hash of the password combined with a "salt" value. When the user signs in we do the same process and check whether the current hash equals to the stored hash.
Google ReCaptcha service is used to make sure that a human is registering and not a bot. In order to use this service you need to create a key: https://www.google.com/recaptcha/admin/create
Note the usage of StartMessageLoop / StopMessageLoop in LoginHelper. These methods block the thread while it waits for the JobDone event.
The Logout handler is quite simple. It invalidates the user session. This means that the next time the user tries access a resource under 'members' folder they will be redirected to the login page.
- All the settings are saved in a file named settings.txt. This makes it simple to test the project locally and then update it on the server without overwriting the server settings file. I'm using Wamp to test it locally with MySQL database.
- Use #MergeLibraries: False. This way you can update the server jar without uploading a large jar file each time. You will need to manually upload the libraries once.
- I'm using this command to run it on the Linux server
nohup ../jre1.7.0_51/bin/java -jar ServerExample.jar > nohup.out &