Understanding Traditional Session Mechanisms and Implementing SSO with CAS in Java
This article explains the limitations of traditional HTTP session handling, explores session sharing strategies for clustered environments, and demonstrates how to build a single sign‑on solution using CAS and OAuth2 concepts with complete Java code examples for filters, controllers, and login pages.
When a product matrix grows, users must switch between multiple systems, leading to poor experience and increased password management costs; a unified authentication approach can improve usability and security.
1. Traditional Session Mechanism – HTTP is stateless, so servers create a new session for each request. Session IDs (e.g., JSESSIONID ) are stored in cookies or URL rewrites, but they cannot be shared across browsers or windows, limiting cross‑system access.
The server checks for a session ID in incoming requests; if absent, it creates a new session and returns the ID to the client.
Typical request flow:
Server reads the session cookie (or URL parameter).
Uses the session ID to retrieve stored data from memory.
If the ID is missing, a new session is created and the ID is sent back in the response.
2. Session Sharing in Clustered Environments
When traffic grows, applications are deployed on multiple servers behind a load balancer, causing a user’s requests to hit different nodes and lose session continuity.
Two main solutions:
Session replication – copy session data to all nodes (high cost, latency issues).
Centralized session storage – store sessions in a shared store such as Redis, allowing all nodes to retrieve the same session data.
3. Multi‑Service Login Challenges and SSO Solutions
Enterprises often have many independent systems, each requiring its own login. Single Sign‑On (SSO) solves this by using a central authentication domain (e.g., ouath.com ) that issues a ticket and stores a sessionId in Redis.
SSO flow (CAS example):
User accesses b.com , is redirected to ouath.com for login.
After successful login, ouath.com creates a ticket and stores <ticket, sessionId> in Redis.
b.com receives the ticket, retrieves the session ID from Redis, loads the user into its own session, and redirects back.
Below are core Java code snippets illustrating the implementation.
public class UserForm implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private String password;
private String backurl;
// getters and setters omitted for brevity
} @Controller
public class IndexController {
@Autowired
RedisTemplate redisTemplate;
@GetMapping("/toLogin")
public String toLogin(Model model, HttpServletRequest request) {
Object userInfo = request.getSession().getAttribute(LoginFilter.USER_INFO);
if (userInfo != null) {
String ticket = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(ticket, userInfo, 2, TimeUnit.SECONDS);
return "redirect:" + request.getParameter("url") + "?ticket=" + ticket;
}
UserForm user = new UserForm();
user.setUsername("laowang");
user.setPassword("laowang");
user.setBackurl(request.getParameter("url"));
model.addAttribute("user", user);
return "login";
}
// other handlers omitted for brevity
} public class LoginFilter implements Filter {
public static final String USER_INFO = "user";
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
Object userInfo = request.getSession().getAttribute(USER_INFO);
String requestUrl = request.getServletPath();
if (!"/toLogin".equals(requestUrl) && !requestUrl.startsWith("/login") && userInfo == null) {
request.getRequestDispatcher("/toLogin").forward(request, response);
return;
}
chain.doFilter(request, response);
}
// init and destroy omitted
}3.2.3 CAS vs OAuth2
CAS (Central Authentication Service) focuses on authenticating users for web SSO, while OAuth2 authorizes third‑party applications to access resources on behalf of a user.
In summary, use CAS for unified login across internal systems and OAuth2 when you need to grant external services limited access to user resources.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.