MCPcopy Index your code
hub / github.com/AmadeusITGroup/HttpSessionReplacer

github.com/AmadeusITGroup/HttpSessionReplacer @v0.4.15

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.4.15 ↗ · + Follow
1,846 symbols 6,538 edges 186 files 660 documented · 36%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

HTTP Session Replacement

Maven Central Javadocs Travis license Dependency Status SonarQube Coverage SonarQube Tech Debt

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:

HTTP Servlet support

The primary usecase is the support for session management for HttpSessions. Support includes the following:

  • Creation of sessions on demand
  • Storing of session attributes between requests
  • Invalidation of sessions
  • Session expiration management
  • Session propagation to clients via cookie and URL.
  • Full support for all non-deprecated HttpSession methods
  • Support for callbacks for values stored in session that implement javax.servlet.http.HttpSessionActivationListener or javax.servlet.http.HttpSessionBindingListener
  • When used with an agent, support for listener objects such as javax.servlet.http.HttpSessionListener and javax.servlet.http.HttpSessionAttributeListener
  • Support for Servlet 3.1 features such as session id switch
  • Compatibility with Servlet 2.5
  • Session stickiness - sessions can be sticked to node and expiration events will then be triggered on node owner of session
  • Support for non-distributable web applications

General Concepts

Session Repository

The 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.

Configuration

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 )
  • Agent configuration (when exists)
  • System properties
  • Default values

Architecture

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.

Session management

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.

Optimized session updates

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

Session id

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.

UUID based session id

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.

Random session id

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.

Random session id without Luhn checksum matching substrings

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.

Session format

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.

Session isolation

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.

Session id propagation between webapps

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.

Session propagation

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).

Cookie Session Management

The session is stored as a UUID inside a cookie. The cookie name is one of the following by descending order of priority:

  • Using the com.amadeus.session.sessionName initialization parameter of the ServletContext.
  • Using the 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

Extension points exported contracts — how you extend this code

SessionIdProvider (Interface)
Implementations of this interface are responsible for generating new session ids and parsing/cleaning the received ones. [6 …
session-replacement/src/main/java/com/amadeus/session/SessionIdProvider.java
ResponseFacade (Interface)
Used to wrap implementation's response for transactions. @param the result type [6 implementers]
session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisFacade.java
SessionRepository (Interface)
Implementation of session storage. If repository stores session remotely, the values stored in session should be {@link [4 …
session-replacement/src/main/java/com/amadeus/session/SessionRepository.java
SessionRepositoryFactory (Interface)
Implementations of this class create instances of SessionRepository for the given configuration. [4 implementers]
session-replacement/src/main/java/com/amadeus/session/SessionRepositoryFactory.java
SerializerDeserializer (Interface)
Implementations of this interface provide serialization/deserialization logic for objects in session. [4 implementers]
session-replacement/src/main/java/com/amadeus/session/SerializerDeserializer.java

Core symbols most depended-on inside this repo

get
called by 156
session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisFacade.java
encode
called by 145
session-replacement/src/main/java/com/amadeus/session/repository/redis/SafeEncoder.java
getValue
called by 97
session-replacement/src/main/java/com/amadeus/session/ExecutorFacade.java
getAttribute
called by 83
session-replacement/src/main/java/com/amadeus/session/RequestWithSession.java
getId
called by 78
session-replacement/src/main/java/com/amadeus/session/SessionData.java
getSession
called by 68
session-replacement/src/main/java/com/amadeus/session/SessionManager.java
println
called by 60
session-replacement/src/main/java/com/amadeus/session/servlet/HttpResponseWrapper.java
info
called by 57
session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisFacade.java

Shape

Method 1,625
Class 201
Interface 17
Enum 3

Languages

Java100%

Modules by API surface

session-replacement/src/main/java/com/amadeus/session/SessionConfiguration.java69 symbols
session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisFacade.java47 symbols
session-replacement/src/main/java/com/amadeus/session/RepositoryBackedSession.java47 symbols
session-replacement/src/main/java/com/amadeus/session/servlet/HttpResponseWrapper.java45 symbols
session-agent/src/test/java/com/amadeus/session/agent/MockServletContext.java45 symbols
integration-tests/agent-tests/src/test/java/com/amadeus/session/sample/MockServletContext.java45 symbols
session-replacement/src/main/java/com/amadeus/session/repository/redis/JedisClusterFacade.java41 symbols
session-replacement/src/main/java/com/amadeus/session/repository/redis/RedisSessionRepository.java40 symbols
session-replacement/src/test/java/com/amadeus/session/repository/redis/TestJedisPoolFacade.java36 symbols
session-replacement/src/test/java/com/amadeus/session/repository/redis/TestJedisClusterFacade.java35 symbols
session-replacement/src/main/java/com/amadeus/session/repository/redis/JedisPoolFacade.java35 symbols
session-replacement/src/main/java/com/amadeus/session/SessionManager.java35 symbols

For agents

$ claude mcp add HttpSessionReplacer \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact