会话 (COOKIE与SESSION)

未匹配的标注

Cookie

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

@RestController
public class DataController {

    // 设置cookie
    @GetMapping("/set-cookie")
    public String getInfo() {
        // 创建 Cookie
        Cookie cookie = new Cookie("user_token", "123456");
        // 设置有效期(秒),-1 表示浏览器关闭后失效,0 表示立即删除
        cookie.setMaxAge(7 * 24 * 60 * 60); // 7天
        // 设置路径(默认为当前接口路径,设为 "/" 表示全站有效)
        cookie.setPath("/");
        // 可选:设置域名(如 .example.com 允许子域名共享)
        // cookie.setDomain(".example.com");
        // 可选:启用 HTTPS 安全传输
        // cookie.setSecure(true);
        // 可选:禁止 JavaScript 访问(防 XSS)
        cookie.setHttpOnly(true);

        // 添加 Cookie 到响应
        response.addCookie(cookie);
        return "Cookie 已设置";
    }

    // 删除cookie
    @GetMapping("/delete-cookie")
    public String deleteCookie(HttpServletResponse response) {
        Cookie cookie = new Cookie("user_token", null);
        cookie.setMaxAge(0); // 立即失效
        cookie.setPath("/"); // 必须与设置时的路径一致
        response.addCookie(cookie);
        return "Cookie 已删除";
    }

    // 读取cookie
    @GetMapping("/read-cookie")
    public String readCookie(@CookieValue(name = "user_token", defaultValue = "unknown") String token) {
        return "Cookie 值: " + token;
    }

    // 遍历所有 Cookie
    @GetMapping("/read-all-cookies")
    public String readAllCookies(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            return "无 Cookie";
        }
        StringBuilder sb = new StringBuilder();
        for (Cookie cookie : cookies) {
            sb.append(cookie.getName()).append(": ").append(cookie.getValue()).append("<br>");
        }
        return sb.toString();
    }
}

// Spring Boot 2.4+ 支持通过配置文件设置默认 Cookie 属性

# application.properties
# 设置所有 Cookie 的 SameSite 属性(Strict/Lax/None)
server.servlet.session.cookie.same-site=lax
# 启用 Secure(仅 HTTPS)
server.servlet.session.cookie.secure=true
# 设置 HttpOnly
server.servlet.session.cookie.http-only=true

SESSION

快速使用 Session

直接通过 HttpServletRequest 存取 Session 数据

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@RestController
public class SessionController {

    // 写入 Session
    @GetMapping("/set-session")
    public String setSession(HttpServletRequest request) {
        HttpSession session = request.getSession(); // 获取或创建 Session
        session.setAttribute("user", "Alice");
        return "Session 已设置";
    }

    // 读取 Session
    @GetMapping("/get-session")
    public String getSession(HttpServletRequest request) {
        HttpSession session = request.getSession(false); // 不创建新 Session
        if (session != null) {
            return "用户名: " + session.getAttribute("user");
        }
        return "Session 不存在";
    }

    // 删除 Session
    @GetMapping("/invalidate-session")
    public String invalidateSession(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate(); // 销毁 Session
        }
        return "Session 已销毁";
    }
}

配置 Session 超时时间

在 application.properties 中设置(单位:秒)

# 设置 Session 超时时间(默认 30 分钟)
server.servlet.session.timeout=1800
# 配置 Session Cookie 属性
server.servlet.session.cookie.name=MY_SESSION
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true
server.servlet.session.cookie.same-site=lax

使用 Spring Session 持久化

将会话存储到外部系统(如 Redis、数据库),实现分布式共享。

(1) 存储到 Redis
步骤 1:添加依赖

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

步骤 2:配置 Redis 连接

# application.properties
spring.redis.host=localhost
spring.redis.port=6379

步骤 3:启用 Redis Session

@EnableRedisHttpSession // 添加在启动类或配置类上
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4. 通过注解简化操作
使用 @SessionAttributes@SessionAttribute 注解管理 Session 数据。

(1) 类级别声明 Session 属性

@Controller
@SessionAttributes("user") // 声明此控制器会将 "user" 存入 Session
public class UserController {

    @GetMapping("/login")
    public String login(Model model) {
        model.addAttribute("user", "Alice"); // 自动存入 Session
        return "redirect:/dashboard";
    }
}

(2) 方法参数读取 Session

@GetMapping("/dashboard")
public String dashboard(@SessionAttribute(name = "user", required = false) String user) {
    if (user == null) {
        return "redirect:/login";
    }
    return "欢迎," + user;
}

5. 安全性建议

  1. Session 固定攻击防护:
    在用户登录成功后调用 session.changeSessionId() 重置 Session ID。
  2. 敏感数据加密:
    避免在 Session 中存储敏感信息(如密码),或使用加密存储。
  3. 结合 Spring Security:
    使用 Spring Security 自动管理 Session 安全性(如并发控制、过期处理)。

6. 验证 Session 存储
若使用 Redis,检查 Redis 中是否生成 Session 键:

$ redis-cli
127.0.0.1:6379> KEYS "spring:session:*"
1) "spring:session:sessions:4e9d5b1a-3e4f-4a7c-bb2d-6d8e3f5a1b2c"

总结
| 操作 | 代码示例 |
|——————–|——————————————|
| 写入 Session | session.setAttribute("key", value) |
| 读取 Session | session.getAttribute("key") |
| 销毁 Session | session.invalidate() |
| 分布式 Session | @EnableRedisHttpSession + Redis 配置 |
| 超时配置 | server.servlet.session.timeout=1800 |

Session 适用于短期用户状态管理(如登录态),结合 Spring Security 或 Redis 可满足复杂场景需求。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
唐章明
讨论数量: 0
发起讨论 查看所有版本


暂无话题~