一、 实现代码
1. 创建登录控制器:
首先,创建一个控制器类,包含登录处理方法。在这个方法中,我们将验证用户名和密码,并在成功时设置会话。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
public class LoginController {
@PostMapping("/login")
@ResponseBody
public String login(
@RequestParam("username") String username,
@RequestParam("password") String password,
HttpServletRequest request,
HttpServletResponse response) {
// 简单的验证逻辑,实际应用中应该使用更安全的方法验证用户名和密码
if ("admin".equals(username) && "password".equals(password)) {
// 验证成功,创建或获取会话
HttpSession session = request.getSession(true); // 不存在则创建 session
session.setAttribute("username", username); // 存储用户信息到会话中
// 这里有一个隐藏逻辑:当你在Spring Boot应用中调用登录接口(如/login接口)并成功认证后,
// Spring Boot应用运行的Servlet容器(默认可能是Tomcat)会自动创建一个HTTP会话(HttpSession)。
// 作为这一过程的一部分,容器会生成一个唯一的会话ID,并将此ID作为JSESSIONIDCookie写入到HTTP响应头中。
// 也就是说,会将 sessionId 写到 cookie 中,key 为 JSESSIONID
// Cookie sessionCookie = new Cookie("JSESSIONID", session.getId());
// response.addCookie(sessionCookie);
// 登录成功,重定向到主页或其他页面
return "redirect:/home";
} else {
// 验证失败,返回错误信息或重定向到登录页面
return "redirect:/login?error=true";
}
}
}
2. 验证会话
在其他需要验证的接口中,你可以检查HttpSession是否存在特定的属性(如用户名),以此来判断用户是否已登录,最好用拦截器全局拦截。
@PostMapping("/someProtectedResource")
@ResponseBody
public String accessProtectedResource(HttpServletRequest request) {
HttpSession session = request.getSession(false); // 不创建新会话,仅获取现有会话
if (session != null && session.getAttribute("username") != null) {
// 用户已登录,继续处理请求
return "Welcome, " + session.getAttribute("username");
// 同样这里有个隐藏逻辑:服务端会获取 cookie 中的 JSESSIONID,并且比较 cookie 中的 JSESSIONID
// 和 当前会话的 sessionId是否相同
} else {
// 用户未登录,返回未授权信息或重定向到登录页
return "Unauthorized";
}
}
二、 注意事项
- 安全性:
- Cookie劫持:确保通过HTTPS传输Cookie,以防中间人攻击窃取Cookie中的会话ID。
- XSS攻击:防范跨站脚本攻击,攻击者可能会通过这种方式偷取用户的Cookie。
- CSRF攻击:实施CSRF防护措施,因为仅依赖Cookie无法验证请求的起源。
- Cookie限制:用户浏览器对Cookie的数量、大小和域名有不同限制,可能导致问题。
- 性能与扩展性:
- 服务器内存:服务器需要为每个活跃会话分配内存,大量并发会话可能消耗大量资源。
- 分布式系统:在分布式环境下,需实现Session共享或粘性会话,否则用户可能在不同服务器间跳转时丢失会话。(Spring Session)
- 有效期管理:
- 适时终止会话,如用户长时间未活动后,以释放服务器资源。
- 兼容性和标准:
- 不同浏览器对Cookie的支持和限制可能有所不同,需要进行兼容性测试。