API
A Java Servlet (Servlet) application uses API methods below to access session related function.
package javax.servlet.http;
public interface HttpServletRequest extends ServletRequest {
public HttpSession getSession(boolean create);
public HttpSession getSession();
public String changeSessionId();
public String getRequestedSessionId();
public boolean isRequestedSessionIdValid();
public boolean isRequestedSessionIdFromCookie();
public boolean isRequestedSessionIdFromURL();
@Deprecated
public boolean isRequestedSessionIdFromUrl();
...
}
- These methods are implemented by Servlet container (e.g. Tomcat)
- Session object has interface javax.servlet.http.HttpSession, and normally its lifecycle is maintainanced by Servlet container. In Tomcat it is org.apache.catalina.session.StandardSession, wrapped by org.apache.catalina.session.StandardSessionFacade
Association between HTTP connection and session object
HTTP is stateless protocol, when Servlet application needs to store something into session object, it calls following methods to retrieve it.
javax.servlet.http.HttpServletRequest.getSession();
// or
javax.servlet.http.HttpServletRequest.getSession(true);
Servlet container instantiates session object, creates session id and associates it with HTTP connection by writing session cookie information (default identifier is JSESSIONID).
Set-Cookie: JSESSIONID=14AE061861E1F5979F28A3D5D742A850; Path=/; HttpOnly
The implementation of Tomcat 9 is org.apache.catalina.connector.Request#doGetSession. Writing
session cookie is performed by following code
// Creating a new session cookie based on that session
if (session != null && trackModesIncludesCookie) {
Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie(
context, session.getIdInternal(), isSecure());
response.addSessionCookieInternal(cookie);
}
org.apache.catalina.connector.Response#addSessionCookieInternal is called
/**
* Special method for adding a session cookie as we should be overriding
* any previous.
*
* @param cookie The new session cookie to add the response
*/
public void addSessionCookieInternal(final Cookie cookie) {
if (isCommitted()) {
return;
}
String name = cookie.getName();
final String headername = "Set-Cookie";
final String startsWith = name + "=";
String header = generateCookieString(cookie);
boolean set = false;
MimeHeaders headers = getCoyoteResponse().getMimeHeaders();
int n = headers.size();
for (int i = 0; i < n; i++) {
if (headers.getName(i).toString().equals(headername)) {
if (headers.getValue(i).toString().startsWith(startsWith)) {
headers.getValue(i).setString(header);
set = true;
}
}
}
if (!set) {
addHeader(headername, header);
}
}
In next HTTP request, the session id is provided in cookie header
GET /login HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://localhost:8080/
Connection: keep-alive
Cookie: JSESSIONID=14AE061861E1F5979F28A3D5D742A850
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
The application gets saved data by retrieving session object, calls
javax.servlet.http.HttpServletRequest.getSession();
// or
javax.servlet.http.HttpServletRequest.getSession(false);
In Tomcat 9 retrieves session object is also processed by org.apache.catalina.connector.Response#addSessionCookieInternal. Following code is for loading session object
// Return the requested session if it exists and is valid
Manager manager = context.getManager();
if (manager == null) {
return null; // Sessions are not supported
}
if (requestedSessionId != null) {
try {
session = manager.findSession(requestedSessionId);
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("request.session.failed", requestedSessionId, e.getMessage()), e);
} else {
log.info(sm.getString("request.session.failed", requestedSessionId, e.getMessage()));
}
session = null;
}
if ((session != null) && !session.isValid()) {
session = null;
}
if (session != null) {
session.access();
return session;
}
}
Other API calls
// change session id, but session object created in Servlet container will not be destroyed
javax.servlet.http.HttpServletRequest.changeSessionId();
// Unassociate current session object
javax.servlet.http.HttpSession.invalidate();