This project provides session management including, possibly, distributed session repository for JEE and other java containers. Default implementation comes with in-memory and Redis based implementation.
The project is inspired by Spring Session project and reuses some of redis logic from it. Its objective is to avoid any dependency on Spring libraries, and, so, make it usable in applications that don't use Spring, or that use an older version. The implementation, however, uses the Jedis library directly. This makes the algorithm easier to port to other languages.
The project aims to make session management transparent for existing webapps (zero code change) and as compatible as possible with wide variety of the JEE containers, all the while offering full support for session API including different session listeners.
Redis support includes both single instance, sentinel based and cluster modes. Two session expiration strategies are available when using Redis. One is based on Redis notifications, and antoher on sorted sets (ZRANGE).
Useful links:
The primary usecase is the support for session management for HttpSessions.
Support includes the following:
HttpSession methodsjavax.servlet.http.HttpSessionActivationListener or
javax.servlet.http.HttpSessionBindingListenerjavax.servlet.http.HttpSessionListener and
javax.servlet.http.HttpSessionAttributeListenerThe session information needs to be stored between server request. This storage is called session repository. Different repository implementations are supported by the session replacement mechanism.
Most of the configuration can be specified with ServletContexts initialization
parameters, system properties and some paramaters can be provided via the agent.
Unless otherwise specified the general rule for priority of configuration is as
follows in descending order:
ServletContexts initiate parameters (set through web.xml or programmatically since Servlet 3.x )Here is the block diagram of the architecture:
+--------------------------------------------------+
| |
| +---+ +-------------------------------+ |
| | | | | |
| | | | | |
| | * | | | |
| | F | | | |
| | I | Wrapped | WEB APPLICATION | |
| | L | request | | |
HTTP | | T |--------->| | |
---->| | E | | | |
HTTPS| | R | | | |
| | * | | | |
| | | +-------------------------------+ |
| | | ^ |
| | | Session interaction | |
| | | v |
| | +------------------------------------------+ |
| | *Session-management* | |
| +----------------------------------------------+ |
| Container (e.g. JBoss, jetty, tomcat) |
+-------------------------------------+------------+
| JVM | *Agent* |
+-------------------------------------+------------+
In the above picture, Agent, Filter and Session-management are modules added to support session storage in repository.
The Filter wraps all incoming requests to allow session retrieval and commit. When using the agent, all filters have code to wrap incoming requests, however, only the first one will wrap it. The following filter in chain will return the request it received. The canonical implementation of a filter is com.amadeus.session.servlet.SessionFilter
The Session-management is intercepting all interactions with sessions and communicates with the session repository. Normally, unless using container specific interface, container should not be aware of the existence of the session.
The Agent performs instrumentation as described below.
The general algorithm for managing sessions is independent of the underlying storage. It has the following characteristics:
Session retrieval from repository.
New session creation of session with cryptographically secure session id. For details see Session id section.
Partial and full session updates allows updating all session attributes or only those that were changed or touched during session request (if repository supports it). For details see Optimized session updates section.
Support for atomic commit allows updating all attributes at once in one transaction or network exchange (if repository supports it).
Support of non-cacheable attributes, i.e. attributes that are stored or retrieved from repository on each access to session attribute. For details see Non-sticky sessions and concurrent access.
Support for session encryption when storing sessions into repository.
The session management keeps track of the attributes that have changed (including deletion) and only updates those. This means if an attribute is written once and read many times we only need to write that attribute once.
Session management can be configured to update all the attributes no matter what or to update all non-primitive wrappers
A session id is an UUID generated using type 4 algorithm, a random sequence of bytes encoded in modified base64 algorithm, or a random sequence of bytes encoded in modified base64 algorithm that doesn't allow substrigns that match Luhn checksum. If a request is made for a session with an id that is expired, not valid or not present in the repository, the id is invalidated and a new one is generated. This prevents simple session fixation attack scenario.
The UUID based session id is activated by setting servlet or system property
com.amadeus.session.id to uuid.
UUID based session id is the default mechanism at the moment,
but this may change before a final release.
If the servlet parameter or system property
com.amadeus.session.noHyphensInId is set to true,
hyphens are removed from UUID.
The random session id is activated by setting servlet or system property
com.amadeus.session.id to random.
This is default strategy.
Random session id length is specified in bytes using the servlet parameter or system property
com.amadeus.session.id.length.
The length of the id as a string will be 4 characters for
each 3 bytes of the id (with padding up to a number that divides by 4).
E.g for 1, 2 or 3 bytes length there will be 4 characters in the id string,
for 4, 5 or 6 there will be 8, etc.
The random session id without substrings matching Lunh checksum is activated by
setting servlet or system property com.amadeus.session.id to no-luhn. This
is useful when there is logic that conceals credit card information (credit
card numbers are sequences of numbers that match Luhn checksum).
The session id length is specified in bytes using the servlet parameter or system property
com.amadeus.session.id.length.
The length of the id as a string will be 4 characters for
each 3 bytes of the id (with padding up to a number that divides by 4).
E.g for 1, 2 or 3 bytes length there will be 4 characters in the id string,
for 4, 5 or 6 there will be 8, etc.
It is possible to tweak the generated session id format using proper configuration parameter.
Parameter com.amadeus.session.timestamp can be used to enforce presence of '!xxxxx' at end of generated jsessionid
xxxxx being the number of millis ellapsed since january 1970 and corresponding to UNIX timestamp.
Sessions can be isolated per application. While this is repository dependent, it is expected that repositories support this. This isolation is done using unique identifier called namespace and it should be part of the key or repository choice. The namespace is not communicated to the clients and is only known by the server.
Best practice is to have different namespaces for sessions in different applications or webapps. If applications want to share sessions they can use the same namespace.
In case of webapps, default behavior is that either the namespace is defined using the servlet initialization
parameter com.amadeus.session.namespace, or if not present, the context path of the webapp is used.
NOTE: When the context path is used as namespace, two different application servers with different webapps, having the same context path will share the same session namespace if they use the same repository.
Outside servlet containers the default namespace name is default.
When propagating a session id from one webapp to another (e.g. using RequestDispatcher),
the session id doesn't change.
The first webapp that got the request is the one that controls and sets the session id.
Note however, that by default each webapp will store its sessions in a different namespace even if they use the same session id.
Two builtin strategies are available for session propagation. The first one is based on cookies and is the default one. The second one is based on URL rewriting where the session is appended at the end of the path part of URL (preceding the query).
The session propagation can be configured using web.xml (standard Servlet approach)
<web-app>
...
<session-config>
<tracking-mode>URL</tracking-mode>
</session-config>
</web-app>
It can also be configured using system property or servlet initialization parameter
com.amadeus.session.tracking. Valid values are COOKIE, URL or DEFAULT
(which is same as COOKIE).
The URL rewriting session propagation is not supported on Tomcat 6 based servlet engines (Tomcat 6.x, JBoss 6.x).
The session is stored as a UUID inside a cookie. The cookie name is one of the following by descending order of priority:
com.amadeus.session.sessionName initialization parameter of the ServletContext.com.amadeus.session.sessionName system property.JSESSIONID.In case of HTTPS requests, cookies can be marked as secure.
This can be configured by setting the com.amadeus.session.cookie.secure
initialization parameter or system property to true.
To apply this behavior only when the request is over secured channel
(i.e. HTTPS), set com.amadeus.session.cookie.secure.on.secured.request
to true. In this case if request comes over insecure channel (i.e. HTTP),
the cookie will not be marked as secure. Reason for this behavior is that
application servers are often behind a load balancer or a TLS offloader
which calls them via HTTP, so even though the exchange with client is over HTTPS, application server is not aware of it. In those cases we want to force cookie to
be marked as secure. When application server is either directly exposed
to secured requests or are aware if request is secured via headers injected
by TLS offloaders, this additional property allows using that capability to
select whether cookie should be marked or not.
For Servlet 3.x and later containers, cookies can be marked as HTTP only. This can be configured by setting `com.amadeus
$ claude mcp add HttpSessionReplacer \
-- python -m otcore.mcp_server <graph>