Tuesday 6 October 2015

How Server generates session id

Session id is a unique identifier generated by server, to track user session. Whenever user visits website, server generates session id for that user. Once user logged of from website, session id assigned to this user is destroyed. Some Web servers generate session IDs by simply incrementing static numbers. However most widely used webservers like tomcat, jetty use some algorithm to generate session ids.

In this post, I am going to explain, how Jetty, tomcat generates session id.

How Jetty generates session id?
org.eclipse.jetty.server.session.AbstractSessionIdManager class generates session id. Following is the session id implementation by AbstractSessionIdManager class.
    public String newSessionId(long seedTerm)
    {
        // pick a new unique ID!
        String id=null;
        while (id==null||id.length()==0||idInUse(id))
        {
            long r0=_weakRandom
                    ?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^((seedTerm)<<32))
                    :_random.nextLong();
            if (r0<0)
                r0=-r0;
                    
            // random chance to reseed
            if (_reseed>0 && (r0%_reseed)== 1L)
            {
                if (LOG.isDebugEnabled())
                    LOG.debug("Reseeding {}",this);
                if (_random instanceof SecureRandom)
                {
                    SecureRandom secure = (SecureRandom)_random;
                    secure.setSeed(secure.generateSeed(8));
                }
                else
                {
                    _random.setSeed(_random.nextLong()^System.currentTimeMillis()^seedTerm^Runtime.getRuntime().freeMemory());
                }
            }
            
            long r1=_weakRandom
                ?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^((seedTerm)<<32))
                :_random.nextLong();
            if (r1<0)
                r1=-r1;
            
            id=Long.toString(r0,36)+Long.toString(r1,36);

            //add in the id of the node to ensure unique id across cluster
            //NOTE this is different to the node suffix which denotes which node the request was received on
            if (_workerName!=null)
                id=_workerName + id;
    
        }
        return id;
    }

Length of Session ID in Jetty
id=Long.toString(r0,36)+Long.toString(r1,36);

Above statement generates id, by converting two random positive long numbers to base 36 format. So the maximum length of the id is 26 characters.
public class Main {
 public static void main(String args[]) {
  long r0 = Long.MAX_VALUE;
  long r1 = Long.MAX_VALUE;

  String id = Long.toString(r0, 36) + Long.toString(r1, 36);
  System.out.println(id);
  System.out.println(id.length());
 }
}


AbstractSessionIdManager is an abstract class. Classes HashSessionManager, InfinispanSessionManager, JDBCSessionManager, NoSqlSessionManager extends AbstractSessionIdManager class.

How tomcat generates session id?
org.apache.catalina.SessionIdGenerator interface specify methods to generate session id. SessionIdGenerator  interface specify method setSessionIdLength, to specify the number of bytes for a session ID.

Following are the methods specified by SessionIdGenerator interface.

Method
Description
public String getJvmRoute()
Return the node identifier associated with this node, which will be included in the generated session ID.
public void setJvmRoute(String jvmRoute)
Specify the node identifier associated with this node which will be included in the generated session ID.
public int getSessionIdLength()
Return the number of bytes for a session ID.
public void setSessionIdLength(int sessionIdLength)
Specify the number of bytes for a session ID.
public String generateSessionId()
Generate and return a new session identifier.
public String generateSessionId(String route)
Generate and return a new session identifier.

SessionIdGeneratorBase class implements SessionIdGenerator interface. StandardSessionIdGenerator class extends SessionIdGeneratorBase class, and provides implementation for generateSessionId method.

public class StandardSessionIdGenerator extends SessionIdGeneratorBase {

    @Override
    public String generateSessionId(String route) {

        byte random[] = new byte[16];
        int sessionIdLength = getSessionIdLength();

        // Render the result as a String of hexadecimal digits
        // Start with enough space for sessionIdLength and medium route size
        StringBuilder buffer = new StringBuilder(2 * sessionIdLength + 20);

        int resultLenBytes = 0;

        while (resultLenBytes < sessionIdLength) {
            getRandomBytes(random);
            for (int j = 0;
            j < random.length && resultLenBytes < sessionIdLength;
            j++) {
                byte b1 = (byte) ((random[j] & 0xf0) >> 4);
                byte b2 = (byte) (random[j] & 0x0f);
                if (b1 < 10)
                    buffer.append((char) ('0' + b1));
                else
                    buffer.append((char) ('A' + (b1 - 10)));
                if (b2 < 10)
                    buffer.append((char) ('0' + b2));
                else
                    buffer.append((char) ('A' + (b2 - 10)));
                resultLenBytes++;
            }
        }

        if (route != null && route.length() > 0) {
            buffer.append('.').append(route);
        } else {
            String jvmRoute = getJvmRoute();
            if (jvmRoute != null && jvmRoute.length() > 0) {
                buffer.append('.').append(jvmRoute);
            }
        }

        return buffer.toString();
    }

}




Prevoius                                                 Next                                                 Home

No comments:

Post a Comment