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(); } }
No comments:
Post a Comment