- Introduction to Session Tracking
HTTP is a stateless protocol—each request from a client to a server is treated independently. To maintain user context across multiple requests (e.g., keeping a user logged in), web applications use session tracking.
A session begins when a user opens a browser and accesses a web application and ends when the browser or server terminates the connection. During this session, multiple HTTP requests and responses may occur.
Session tracking enables the server to recognize that multiple requests originate from the same client, allowing data sharing across those requests. Common techniques include:
- Cookie: stores data on the client side.
- Session: stores data on the server side, often using a cookie to track the session ID.
- Cookie
2.1 Concept and Workflow
A Cookie is a small piece of data sent by the server and stored in the user's browser. On subsequent requests, the browser automatically includes the cookie in the HTTP headers.
Workflow:
- Client sends request to
ServletA. ServletAcreates aCookieand adds it to the response viaresponse.addCookie().- Browser stores the cookie.
- On next request to
ServletB, the browser includes the cookie in the request header. ServletBretrieves the cookie usingrequest.getCookies().
2.2 Basic Usage
Sending a Cookie:
Cookie userCookie = new Cookie("username", "alice");
response.addCookie(userCookie);
Reading Cookies:
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
if ("username".equals(c.getName())) {
String value = c.getValue();
// process value
}
}
}
2.3 Underlying Mechanism
Cookies rely on two HTTP headers:
Set-Cookie(in response): instructs the browser to store a cookie.Cookie(in request): sends stored cookies back to the server.
2.4 Advanced Details
2.4.1 Cookie Lifetime
- Default: stored in memory (deleted when browser closes).
setMaxAge(seconds):- Positive: persists to disk until expiration.
- Negative: memory-only (default behavior).
- Zero: deletes the cookie immediately.
2.4.2 Storing Non-ASCII Characters
To store Chinese or other Unicode characters, encode before storing and decode when reading:
// Encoding
String encoded = URLEncoder.encode("张三", "UTF-8");
Cookie c = new Cookie("name", encoded);
// Decoding
String decoded = URLDecoder.decode(cookie.getValue(), "UTF-8");
- Session
3.1 Overview
Unlike cookies, sessions store data on the server. The server generates a unique session ID (e.g., JSESSIONID) and sends it to the client as a cookie. The client returns this ID with each request, allowing the server to retrieve the correct session data.
3.2 Basic API
Obtain session and manage attributes:
HttpSession session = request.getSession();
// Store data
session.setAttribute("user", userObject);
// Retrieve data
User u = (User) session.getAttribute("user");
// Remove data
session.removeAttribute("user");
3.3 How Session Works
- First request: server creates a session with a unique ID (e.g.,
10). - Server adds
Set-Cookie: JSESSIONID=10to the response. - Browser stores this cookie.
- Subsequent requests include
Cookie: JSESSIONID=10. - Server uses the ID to locate the session object in memory.
If the browser restarts, the session cookie is lost (unless persisted), and a new session is created.
3.4 Session Management Details
3.4.1 Passivation and Activation
When Tomcat shuts down gracefully, active sessions are serialized to disk (SESSIONS.ser). On restart, they are deserialized back into memory.
3.4.2 Session Timeout and Invalidation
Timeout (default: 30 minutes) can be configured in web.xml:
<session-config>
<session-timeout>30</session-timeout>
</session-config>
Manual invalidation:
session.invalidate(); // Destroys session immediately
- Cookie vs Session
| Aspect | Cookie | Session |
|---|---|---|
| Storage | Client-side | Server-side |
| Security | Less secure (exposed to client) | More secure |
| Size Limit | ~4KB per cookie | No practical limit |
| Lifetime | Configurable (persistent or session-only) | Typically short-lived (e.g., 30 min idle timeout) |
| Server Load | None | Uses memory per session |
Use Cases:
- Cookie: "Remember me", shopping cart (non-sensitive data).
- Session: User authentication, sensitive data, CAPTCHA storage.
- Login and Registration Example
5.1 Requirements
- Login: Validate credentials; support "Remember Me" (7-day persistence via cookie); display error on failure.
- Registration: Collect username, password, and CAPTCHA; validate uniqueness and CAPTCHA; redirect to login on success.
5.2 Implementation Highlights
Database Schema
-- Users
CREATE TABLE tb_user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) UNIQUE,
password VARCHAR(32)
);
-- Brands (post-login view)
CREATE TABLE tb_brand (
id INT PRIMARY KEY AUTO_INCREMENT,
brand_name VARCHAR(20),
company_name VARCHAR(20),
ordered INT,
description VARCHAR(100),
status INT -- 0: disabled, 1: enabled
);
Login Servlet
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String username = ReEncoding.reEncodingToUtf8(req.getParameter("username"));
String password = req.getParameter("password");
String remember = req.getParameter("remember");
User user = userService.login(username, password);
if (user != null) {
if ("1".equals(remember)) {
Cookie u = new Cookie("username", username);
Cookie p = new Cookie("password", password);
u.setMaxAge(604800); // 7 days
p.setMaxAge(604800);
resp.addCookie(u);
resp.addCookie(p);
}
req.getSession().setAttribute("user", user);
resp.sendRedirect(req.getContextPath() + "/selectAll");
} else {
req.setAttribute("login_msg", "Invalid credentials");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
}
Registration with CAPTCHA
CAPTCHA Generation:
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
ServletOutputStream out = resp.getOutputStream();
String code = CheckCodeUtil.outputVerifyImage(100, 50, out, 4);
req.getSession().setAttribute("checkCodeGenerate", code);
}
}
Regisrtation Validation:
String inputCode = req.getParameter("checkCode");
String savedCode = (String) session.getAttribute("checkCodeGenerate");
if (!savedCode.equalsIgnoreCase(inputCode)) {
// Handle error
}
JSP Pages
Login Page (auto-fill from cookie):
<input name="username" value="${cookie.username.value}">
<input name="password" value="${cookie.password.value}" type="password">
Post-login Brand View (from session):
<h1>${user.username}, welcome!</h1>
CAPTCHA Refresh (prevent caching):
document.getElementById("changeImg").onclick = function() {
const img = document.getElementById("checkCodeImg");
img.src = "/app/checkCode?" + new Date().getTime();
};