Saving sessions in Redis and sharing them in PHP and Tomcat
Actually the task is very specific, but maybe this work will be useful to someone else. The question of the appropriateness of sharing Apache and Tomcat I propose to leave out of the discussion. The task was set at work already for granted. It is required to ensure that sessions are stored in Redis for PHP and Tomcat, so that these sessions are shared between them. Prolonged googling failed. Both PHP and Tomcat have session storage facilities in Redis, but they have different storage formats. All 3 projects found for Tomcat serialize sessions in Redis using a binary format for serializing Java objects. PHP and Tomcat also have different identifiers for the Cookie session (PHPSESSID and JSESSID, respectively).
Actually, I had to solve these problems. If possible, I wanted to do everything wisely: without coming up with our own API for working with sessions; without inventing your own function of generating a unique and random ID for the session (in such things it’s easy to mess up, making, as a result, the whole project vulnerable); writing a minimum of code that duplicates functionality already invented by others.
With PHP, everything turned out to be extremely simple. There is a wonderful project that, while saving a session, serializes its attributes in JSON. In addition, PHP makes it possible to change the name of the cookie used on the client using the session-name function . So with PHP it turned out almost nothing and did not need to be done.
Tomcat is getting harder. Among the 3 projects found that provide the ability to store sessions in Redis, there was not one that could save the session in anything other than a binary format for serializing objects in Java, which is somewhat difficult to read using PHP tools (and even if not, it’s certainly bad practice).
However, the Tomcat Redis Session Manager project allows you to use your own object serialization implementations, which allows you to solve the problem of storing a session in Redis in JSON format.
So the PHP session creation code looks like this:
The script in the work looks like this:

As a result, a record with the key - session id and session data serialized in JSON will get into Redis.

Java is a bit more complicated.
First, install the Redis Session Manager. The installation process is described in detail on the official website of the project. We write in context.xml:
Here I do not prescribe parameters that match my default settings (for example, the server is localhost), in addition, the serializationStrategyClass parameter is added, which sets the path to my own implementation of the session serialization class (the code will be lower).
Downloaded tomcat-redis-session-manager-1.2-tomcat-6.jar put in the lib folder of your Tomcat.
The serialization class looks like this:
Here, the Json library is used for serialization in JSON , so if it is not installed, install it.
We compile the class in Jar and put it in the lib folder of your copy of Tomcat. An example of my compilation command:
Of course, the paths to libraries on your machine may vary. Too lazy to compile yourself, take the finished Jar from my Dropbox .
All. After that, you can create sessions in the most usual way, everything works completely transparently. If you followed the steps for Tomcat and created sessions in PHP using the code above, then you have common sessions between Tomcat and PHP.
Just in case, I give an example of creating a session in Tomcat:
As you can see, no specific actions are required, a completely normal session creation code.
Java example result:

Actually, I had to solve these problems. If possible, I wanted to do everything wisely: without coming up with our own API for working with sessions; without inventing your own function of generating a unique and random ID for the session (in such things it’s easy to mess up, making, as a result, the whole project vulnerable); writing a minimum of code that duplicates functionality already invented by others.
With PHP, everything turned out to be extremely simple. There is a wonderful project that, while saving a session, serializes its attributes in JSON. In addition, PHP makes it possible to change the name of the cookie used on the client using the session-name function . So with PHP it turned out almost nothing and did not need to be done.
Tomcat is getting harder. Among the 3 projects found that provide the ability to store sessions in Redis, there was not one that could save the session in anything other than a binary format for serializing objects in Java, which is somewhat difficult to read using PHP tools (and even if not, it’s certainly bad practice).
However, the Tomcat Redis Session Manager project allows you to use your own object serialization implementations, which allows you to solve the problem of storing a session in Redis in JSON format.
To code
Php
So the PHP session creation code looks like this:
# подключаем модуль, предполагается, что вы его скопировали в ваш проект
# в папку, откуда выполняется этот код
require('redis-session-php/redis-session.php');
# переопределяем префикс, под которым будут храниться сессии в
# Redis. Это нужно сделать, т. к. в tomcat-redis-session-manager
# захардкодили, что сессии хранятся без префикса
define('REDIS_SESSION_PREFIX', '');
# в Tomcat мы имя куки поменять не можем, поэтому меняем в PHP
session_name('JSESSIONID');
# собственно начинаем сессию
RedisSession::start();
The script in the work looks like this:

As a result, a record with the key - session id and session data serialized in JSON will get into Redis.

Java is a bit more complicated.
Java
First, install the Redis Session Manager. The installation process is described in detail on the official website of the project. We write in context.xml:
Here I do not prescribe parameters that match my default settings (for example, the server is localhost), in addition, the serializationStrategyClass parameter is added, which sets the path to my own implementation of the session serialization class (the code will be lower).
Downloaded tomcat-redis-session-manager-1.2-tomcat-6.jar put in the lib folder of your Tomcat.
The serialization class looks like this:
package com.radiadesign.catalina.session;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Enumeration;
import java.util.Map;
import java.io.ByteArrayOutputStream;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.util.Iterator;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
public class JSONSerializer implements Serializer {
private ClassLoader loader;
@Override
public void setClassLoader(ClassLoader loader) {
this.loader = loader;
}
@Override
public byte[] serializeFrom(HttpSession session) throws IOException {
// create map to put data here
HashMap sessionData = new HashMap();
// put every attribute of session in newly created map
for (Enumeration keys = session.getAttributeNames(); keys.hasMoreElements();){
String k = (String) keys.nextElement();
sessionData.put(k, session.getAttribute(k));
}
// write it to byte array
Gson gson = new Gson();
return gson.toJson(sessionData).getBytes();
}
@Override
public HttpSession deserializeInto(byte[] data, HttpSession session) throws IOException, ClassNotFoundException {
RedisSession redisSession = (RedisSession) session;
redisSession.setValid(true);
// place data to map
Gson gson = new Gson();
Type mapType = new TypeToken>(){}.getType();
HashMap sessionData = gson.fromJson(new String(data), mapType);
// place attributes to session object
for (Map.Entry entry : sessionData.entrySet())
redisSession.setAttribute(entry.getKey(), entry.getValue());
// return filled session*/
return redisSession;
}
}
Here, the Json library is used for serialization in JSON , so if it is not installed, install it.
We compile the class in Jar and put it in the lib folder of your copy of Tomcat. An example of my compilation command:
javac -cp /usr/share/tomcat6/lib/servlet-api.jar:/usr/share/tomcat6/lib/catalina.jar:/usr/share/tomcat6/lib/tomcat-redis-session-manager-1.2-tomcat-6.jar:/usr/share/tomcat6/lib/gson-2.2.2.jar com/radiadesign/catalina/session/JSONSerializer.java
jar cf jsonserializer.0.1.jar com
Of course, the paths to libraries on your machine may vary. Too lazy to compile yourself, take the finished Jar from my Dropbox .
All. After that, you can create sessions in the most usual way, everything works completely transparently. If you followed the steps for Tomcat and created sessions in PHP using the code above, then you have common sessions between Tomcat and PHP.
Just in case, I give an example of creating a session in Tomcat:
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
public class HelloServlet extends HttpServlet {
public void doGet (HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException
{
PrintWriter out = res.getWriter();
HttpSession session = req.getSession();
out.println("ID: " + session.getId());
session.setAttribute("Name", "kapitoka");
out.println("Set done");
out.println("Get result: " + session.getAttribute("Name"));
out.close();
}
}
As you can see, no specific actions are required, a completely normal session creation code.
Java example result:
