概述

Session 和 Cookie 是 Web 开发中常用的两种技术,用于在服务器和客户端之间维护用户状态和会话信息。它们通常用于用户认证和跟踪用户的登录状态,但在实现方式和应用场景上有所不同。

Cookie(HTTP Cookie)

Cookie 是存储在客户端(通常是浏览器)中的小型文本文件,由服务器发送给客户端,并存储在客户端的文件系统中。它通常包含了一些会话信息,比如用户的身份标识、访问过的页面等。Cookie 是通过 HTTP 协议在客户端和服务器之间传递的。

主要特点:

  1. 存储在客户端,可以设置过期时间。
  2. 每次 HTTP 请求都会携带相应的 Cookie。
  3. 可以通过 JavaScript 进行读写,但受同源策略的限制。
  4. 客户端可以禁用 Cookie。

Session

Session 是存储在服务器端的会话对象,用于跟踪用户在网站上的活动状态。通常,服务器会为每个用户创建一个唯一的会话标识符(Session ID),并将这个 Session ID 存储在 Cookie 中发送给客户端,客户端在后续的请求中会带上这个 Session ID。服务器根据 Session ID 来查找对应的会话对象,从而获取用户的会话信息。

主要特点:

  1. 存储在服务器端,通常存储在内存或数据库中。
  2. 可以存储任意类型的数据,不受客户端限制。
  3. Session 的生命周期通常由服务器控制,默认情况下是会话结束或超时后失效。
  4. 客户端无法直接读取 Session 数据,只能通过服务器提供的接口间接访问。

区别与应用场景

  1. 存储位置:Cookie 存储在客户端,Session 存储在服务器端。
  2. 安全性:由于 Cookie 存储在客户端,可能会受到 XSS(跨站脚本攻击)和 CSRF(跨站请求伪造)等安全威胁,而 Session 存储在服务器端相对安全。
  3. 存储容量:Cookie 的存储容量通常较小(4KB 左右),而 Session 可以存储大量数据。
  4. 生命周期控制:Cookie 的生命周期由设置的过期时间控制,而 1. Session 的生命周期通常由服务器控制。

在实际应用中,Cookie 通常用于存储用户的身份标识和一些基本信息,以便客户端和服务器进行会话跟踪和状态维护;而 Session 则用于存储用户的会话数据,如购物车信息、登录状态等。通常情况下,服务器会将用户的身份认证信息存储在 Session 中,而将 Session ID 存储在 Cookie 中,以实现用户的登录状态跟踪。

应用示例

如下是一个登录程序,登录成功写入session,访问后台admin链接则会进行拦截鉴权,有登录信息则可进行admin管理操作

// 登录程序
@PostMapping(value = "/login")
    public String login(@RequestParam("userName") String userName,
                        @RequestParam("password") String password,
                        @RequestParam("verifyCode") String verifyCode,
                        HttpSession session) {
        if (StringUtils.isEmpty(verifyCode)) {
            session.setAttribute("errorMsg", "验证码不能为空");
            return "admin/login";
        }
        if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
            session.setAttribute("errorMsg", "用户名或密码不能为空");
            return "admin/login";
        }
        String kaptchaCode = session.getAttribute("verifyCode") + "";
        if (StringUtils.isEmpty(kaptchaCode) || !verifyCode.equals(kaptchaCode)) {
            session.setAttribute("errorMsg", "验证码错误");
            return "admin/login";
        }
        AdminUser adminUser = adminUserService.login(userName, password);
        if (adminUser != null) {
            session.setAttribute("loginUser", adminUser.getNickName());
            session.setAttribute("loginUserId", adminUser.getAdminUserId());
            //session过期时间设置为7200秒 即两小时
            //session.setMaxInactiveInterval(60 * 60 * 2);
            return "redirect:/admin/index";
        } else {
            session.setAttribute("errorMsg", "登陆失败");
            return "admin/login";
        }
    }
// 拦截验证程序
package com.site.blog.my.core.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 后台系统身份验证拦截器
 */
@Component
public class AdminLoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        String uri = request.getRequestURI();
        if (uri.startsWith("/admin") && null == request.getSession().getAttribute("loginUser")) {
            request.getSession().setAttribute("errorMsg", "请重新登陆");
            response.sendRedirect(request.getContextPath() + "/admin/login");
            return false;
        } else {
            request.getSession().removeAttribute("errorMsg");
            return true;
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}