Java会话管理案例

wen java案例 1

本文目录导读:

Java会话管理案例

  1. Servlet会话管理示例
  2. 登录页面 (login.jsp)
  3. 使用Spring Boot的会话管理
  4. 关键会话管理最佳实践

我来提供一个完整的Java会话管理案例,包括登录、会话跟踪和登出功能。

Servlet会话管理示例

项目结构

session-management/
├── src/
│   └── com/example/
│       ├── LoginServlet.java
│       ├── LogoutServlet.java
│       ├── DashboardServlet.java
│       └── SessionListener.java
└── web/
    └── WEB-INF/
        └── web.xml

LoginServlet.java

package com.example;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    // 模拟用户数据库
    private static final String VALID_USERNAME = "admin";
    private static final String VALID_PASSWORD = "password123";
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 验证用户凭据
        if (VALID_USERNAME.equals(username) && VALID_PASSWORD.equals(password)) {
            // 获取或创建会话
            HttpSession session = request.getSession(true);
            // 设置会话属性
            session.setAttribute("username", username);
            session.setAttribute("loginTime", System.currentTimeMillis());
            session.setAttribute("role", "USER");
            // 设置会话超时时间(秒)
            session.setMaxInactiveInterval(30 * 60); // 30分钟
            // 重定向到仪表板
            response.sendRedirect("dashboard");
        } else {
            // 登录失败
            request.setAttribute("errorMessage", "用户名或密码错误");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // 显示登录页面
        request.getRequestDispatcher("/login.jsp").forward(request, response);
    }
}

DashboardServlet.java

package com.example;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/dashboard")
public class DashboardServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // 获取会话
        HttpSession session = request.getSession(false);
        // 检查用户是否已登录
        if (session == null || session.getAttribute("username") == null) {
            // 未登录,重定向到登录页面
            response.sendRedirect("login");
            return;
        }
        // 用户已登录,显示仪表板
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String username = (String) session.getAttribute("username");
        long loginTime = (long) session.getAttribute("loginTime");
        String role = (String) session.getAttribute("role");
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<title>用户仪表板</title>");
        out.println("<style>");
        out.println("body { font-family: Arial, sans-serif; margin: 40px; }");
        out.println(".session-info { background: #f0f0f0; padding: 20px; border-radius: 5px; }");
        out.println("</style>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>欢迎," + username + "!</h1>");
        out.println("<div class='session-info'>");
        out.println("<h2>会话信息</h2>");
        out.println("<p>用户名: " + username + "</p>");
        out.println("<p>角色: " + role + "</p>");
        out.println("<p>登录时间: " + new java.util.Date(loginTime) + "</p>");
        out.println("<p>会话ID: " + session.getId() + "</p>");
        out.println("<p>会话超时时间: " + session.getMaxInactiveInterval() + " 秒</p>");
        out.println("</div>");
        out.println("<br>");
        out.println("<a href='logout'>退出登录</a>");
        out.println("</body>");
        out.println("</html>");
    }
}

LogoutServlet.java

package com.example;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // 获取会话(不创建新会话)
        HttpSession session = request.getSession(false);
        if (session != null) {
            // 清除所有会话属性
            session.invalidate(); // 使会话失效
        }
        // 重定向到登录页面
        response.sendRedirect("login");
    }
}

SessionListener.java

package com.example;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionListener implements HttpSessionListener {
    private static int activeSessions = 0;
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        activeSessions++;
        System.out.println("会话创建 - 当前活跃会话数: " + activeSessions);
        System.out.println("会话ID: " + se.getSession().getId());
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        activeSessions--;
        System.out.println("会话销毁 - 当前活跃会话数: " + activeSessions);
        System.out.println("会话ID: " + se.getSession().getId());
        // 清理会话相关的资源
        HttpSession session = se.getSession();
        String username = (String) session.getAttribute("username");
        if (username != null) {
            System.out.println("用户 " + username + " 已登出");
        }
    }
    public static int getActiveSessions() {
        return activeSessions;
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>Session Management Demo</display-name>
    <!-- 全局会话超时设置(分钟) -->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    <!-- 欢迎页面 -->
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
</web-app>

登录页面 (login.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">用户登录</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 50px; }
        .login-form { 
            width: 300px; 
            margin: 0 auto; 
            padding: 20px; 
            border: 1px solid #ccc; 
            border-radius: 5px;
        }
        .form-group { margin-bottom: 15px; }
        label { display: block; margin-bottom: 5px; }
        input[type="text"], input[type="password"] { 
            width: 100%; 
            padding: 8px; 
            box-sizing: border-box;
        }
        .error { color: red; margin-bottom: 10px; }
        button { 
            background: #4CAF50; 
            color: white; 
            padding: 10px 15px; 
            border: none; 
            cursor: pointer; 
            width: 100%;
        }
        button:hover { background: #45a049; }
    </style>
</head>
<body>
    <div class="login-form">
        <h2>用户登录</h2>
        <% if(request.getAttribute("errorMessage") != null) { %>
            <div class="error"><%= request.getAttribute("errorMessage") %></div>
        <% } %>
        <form action="login" method="post">
            <div class="form-group">
                <label for="username">用户名:</label>
                <input type="text" id="username" name="username" required>
            </div>
            <div class="form-group">
                <label for="password">密码:</label>
                <input type="password" id="password" name="password" required>
            </div>
            <button type="submit">登录</button>
        </form>
        <p style="text-align: center; margin-top: 15px;">
            默认账号: admin / password123
        </p>
    </div>
</body>
</html>

使用Spring Boot的会话管理

Spring Boot应用配置

// 在application.properties中配置
server.servlet.session.timeout=30m
server.servlet.session.cookie.name=MYAPP_SESSIONID
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true
server.servlet.session.tracking-modes=cookie

Spring Security配置示例

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/login", "/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/dashboard")
                .permitAll()
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?logout")
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID")
                .permitAll()
                .and()
            .sessionManagement()
                .maximumSessions(1) // 每个用户最多一个会话
                .maxSessionsPreventsLogin(false) // 允许新登录,使旧会话失效
                .expiredUrl("/login?expired");
    }
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
}

关键会话管理最佳实践

安全建议

// 1. 创建会话后的安全设置
public static void secureSession(HttpSession session) {
    // 生成新的会话ID(防止会话固定攻击)
    session.invalidate(); // 使旧会话失效
    session = session.getRequest().getSession(true); // 创建新会话
    // 设置会话属性
    session.setAttribute("user", user);
    session.setAttribute("ipAddress", request.getRemoteAddr());
    session.setAttribute("userAgent", request.getHeader("User-Agent"));
}
// 2. 验证会话上下文
public static boolean validateSession(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if (session == null) return false;
    String storedIp = (String) session.getAttribute("ipAddress");
    String currentIp = request.getRemoteAddr();
    String storedAgent = (String) session.getAttribute("userAgent");
    String currentAgent = request.getHeader("User-Agent");
    // 验证IP和User-Agent是否变化
    return storedIp != null && storedIp.equals(currentIp) &&
           storedAgent != null && storedAgent.equals(currentAgent);
}
// 3. 会话失效处理
public static void invalidateSession(HttpSession session) {
    if (session != null) {
        // 清除所有属性
        Enumeration<String> attributeNames = session.getAttributeNames();
        while (attributeNames.hasMoreElements()) {
            String attributeName = attributeNames.nextElement();
            session.removeAttribute(attributeName);
        }
        // 使会话失效
        session.invalidate();
    }
}

这个示例展示了Java中会话管理的核心概念,包括:

  • 创建和销毁会话
  • 会话属性管理
  • 会话超时控制
  • 会话监听器
  • 安全最佳实践
  • Spring Boot集成示例

抱歉,评论功能暂时关闭!