概述
Session 和 Cookie 是 Web 开发中常用的两种技术,用于在服务器和客户端之间维护用户状态和会话信息。它们通常用于用户认证和跟踪用户的登录状态,但在实现方式和应用场景上有所不同。
Cookie(HTTP Cookie)
Cookie 是存储在客户端(通常是浏览器)中的小型文本文件,由服务器发送给客户端,并存储在客户端的文件系统中。它通常包含了一些会话信息,比如用户的身份标识、访问过的页面等。Cookie 是通过 HTTP 协议在客户端和服务器之间传递的。
主要特点:
- 存储在客户端,可以设置过期时间。
- 每次 HTTP 请求都会携带相应的 Cookie。
- 可以通过 JavaScript 进行读写,但受同源策略的限制。
- 客户端可以禁用 Cookie。
Session
Session 是存储在服务器端的会话对象,用于跟踪用户在网站上的活动状态。通常,服务器会为每个用户创建一个唯一的会话标识符(Session ID),并将这个 Session ID 存储在 Cookie 中发送给客户端,客户端在后续的请求中会带上这个 Session ID。服务器根据 Session ID 来查找对应的会话对象,从而获取用户的会话信息。
主要特点:
- 存储在服务器端,通常存储在内存或数据库中。
- 可以存储任意类型的数据,不受客户端限制。
- Session 的生命周期通常由服务器控制,默认情况下是会话结束或超时后失效。
- 客户端无法直接读取 Session 数据,只能通过服务器提供的接口间接访问。
区别与应用场景
- 存储位置:Cookie 存储在客户端,Session 存储在服务器端。
- 安全性:由于 Cookie 存储在客户端,可能会受到 XSS(跨站脚本攻击)和 CSRF(跨站请求伪造)等安全威胁,而 Session 存储在服务器端相对安全。
- 存储容量:Cookie 的存储容量通常较小(4KB 左右),而 Session 可以存储大量数据。
- 生命周期控制: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 {
}
}