In the last post, we showed how to create HTML forms with global variables and explained why this approach has several limitations. Today we will show a more flexible approach using sessions, and also discuss the security implications.
What is a session?
Let's consider once more our last example, the "First name, Last name"-Form sheet. Obviously its usage is extremely limited: For example, no matter when or under which circumstances the user submits the form sheet, it will always render the same result. This is because the HTML protocol is stateless: The server does not "remember" if a new request came from the same client or not.
However, most applications require more complex handling than that. For example, you might want to adapt what is displayed on screen depending on previous information from that user - in other words, we need a way to manage the conversation between the client and the web server to make our application stateful.
We can solve this problem using HTTP Sessions.
Initializing a session
In order to establish a permanent session, we need to call the
app function during startup - for example, before we call the HTML-function.
(app) (html 0 "Simple Session *Css NIL ...
If we open the window again, it seems unchanged. However, if we press submit, we can see that the URL is changing directly after submission ( visit here to see the hosted version on picolisp.com):
Here you can find the code of the example.
The port has changed from 8080 to 44573, and the file name is prepended by a long number followed by
~. What has happened?
A child process of the server has been started, which is now listening on a new, free port. The long number (in the example: 64805618275437997) is the session key which is used to identify the client towards the server.
We can identify the new server process also using the command line tool
ps in Linux:
$ ps ax | grep picolisp 14151 pts/2 S+ 0:00 /usr/bin/picolisp /usr/lib/picolisp/lib.l /usr/bin/pil @lib/http.l @lib/xhtml.l @lib/form.l --server 8080 + 14172 pts/2 S+ 0:00 /usr/bin/picolisp /usr/lib/picolisp/lib.l /usr/bin/pil @lib/http.l @lib/xhtml.l @lib/form.l --server 8080 +
Or, if you're really curious, you can also try to check the ports where picolisp is listening with
$ netstat -ltup | grep picolisp tcp6 0 0 [::]:http-alt [::]:* LISTEN 14151/picolisp tcp6 0 0 [::]:47249 [::]:* LISTEN 14172/picolisp
As you can see, picolisp is listening on port "http-alt" (which is 8080) and on port 47249, as we could also see on the URL.
Use the debugger
Another effect of our newly established client-server connection is that you can use the debugger to check the status: As soon as the connection is established, a colon
: appears in the terminal window of the application server.
$ pil @lib/http.l @lib/xhtml.l @lib/form.l --server 8080 + :
Let's check the value of our
: *FirstName -> "Mia"
Application vs. production environment
Sessions are typically needed in "real" applications, i. e. in production environments - we won't need it as long as we fiddle on our code all by ourselves on our local computer.
This whole topic is certainly worth its own post and we will discuss it in more depth at the end of this tutorial. Nevertheless we should also discuss a few points now.
Will the user be able to see the port change?
As we saw before, the session caused the URL to jump from port 8080 to port 44573. In real-world applications, this will create problems: For example these ports must be open in the firewall, and situations depending on the "same origin policy" won't work.
Therefore we need to use an utility called
httpGate to take care of the following tasks:
- Provide a single application entry port (e.g. 80 or 443).
- Allow PicoLisp applications to run as non-root.
- Start application servers on demand.
- Handle HTTPS/SSL communication.
This means that every client will build up the connection to the server on the entry port, which is then forwarded on the server side to a dedicated listening port, for example port 12345. This listening port will be visible in the URL:
The listening ports are closed down automatically after 7 minutes.
As already mentioned, we will come back to the production environment at a later post - but if you want to know more now, read here.
Also, cookies make it really difficult to maintain multiple sessions in the same browser. Then you need complicated workarounds like for example proxy servers.
Cons: URL links are often shared by the user, and they might be unaware that the URL contains sensitive information. They could accidentially post their session key, for example in a forum or email, and anybody who has access to it can hijack the session while the key is valid. Or - even worse - if a malicious user sends the victim a prepared URL with an own valid session key and takes over the session ("Session Fixation Attack"). One way to solve this problem is to restrict the connections per key to the same IP addressor network. Obviously you should also define a time-out for the session to minimize the risk.
It should be mentioned that neither cookie nor URL session handling is secure unless the whole traffic is encrypted (e.g. https). Otherwise either way will be completely readable by anyone who is intercepting the traffic, for example in a public network. And in any case, you should also implement a server-side validation to double-check if the session key is valid.
So, the question "Are cookies safer than URL session keys?" can be answered with a clear "It depends" - in any case, you should know what you are doing and have the security aspects in mind. Many security holes come from misconfiguration and neglectance, not from the architecture itself.
Of course, you can also do both: the URL sessions plus an authentication cookie. This is actually quite a common practice, and we will show in a later post how to do this in PicoLisp.
Now that our session is established, we can finally start to play with the PicoLisp GUI Framework! However, we need some knowledge about objects and classes - so we will do some Object Oriented Prorgamming theory first.