Spring Boot Session
会话管理是用于安全控制一个用户或者实体对基于网络的应用/服务的多个请求的过程。
HTTP用于网站和浏览器之间的交流,而会话则是同一个用户创建的一系列的HTTP请求和事务。
会话管理的实现规定了用户、网络应用之间共享和持续交换会话ID的过程。
由于HTTP协议的无状态,为了跟踪客户的行为,我们需要会话管理。会话管理是一个网络容器框架,用于为特定的用户储存会话数据。
我们可以通过以下方法处理会话:
-
Cookies
网站发送的数据被储存在用户的本地浏览器中
-
隐藏的表达字段
在隐藏的数据中,对用户不可见也不可修改,当用户提交表单时,隐藏数据会被发送。
-
URL重写
修改URL的参数
-
HttpSession(网络会话)
允许数据与单个访问者绑定
在分布式环境中,我们可以通过以下方式管理会话:
-
粘性会话(Sticky Session)
在这种类型的会话中,负载均衡将把通过一个客户的请求路由到同一个节点,如果这个节点发生故障,则会话会丢失。
-
复制会话(Session Replication)
为了克服粘性会话的问题,会话复制将会话数据复制到多个服务器,当任何节点发生故障后,会话数据可以转移到另外的节点。
-
持久数据储存中的会话数据(Session Data in a Persistent DataStore)
还有一种情况下,会话数据并不会储存在服务器中,取而代之的是,它会被储存在数据库里,并且拥有唯一id
SESSION_ID
。
Spring Session
Spring Session包含下述组件:
-
Spring Session Core
Spring Session的核心APIs
-
Spring Session Data Redis
提供Redis数据库会话管理的会话存储库
-
Spring Session JDBC
提供关系数据库会话管理的会话存储库
-
Spring Session Hazelcast
提供Hazelcast会话管理的会话存储库
默认情况下,Apache Tomcat在内存中储存HTTP会话管理的对象。为了管理Spring Boot 会话管理,HTTPSession会被用于通过Spring Session JDBC在持久层中存储会话信息。
maven中导入
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
</dependency>
创建Controller
为了处理用户的请求,处理用户的数据并将数据存储在会话的 NOTES_SESSION
属性中。
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class SpringBootSessionController {
@PostMapping("/addNote")
public String addNote(@RequestParam("note") String note, HttpServletRequest request) {
//get the notes from request session
List<String> notes = (List<String>) request.getSession().getAttribute("NOTES_SESSION");
//check if notes is present in session or not
if (notes == null) {
notes = new ArrayList<>();
// if notes object is not present in session, set notes in the request session
request.getSession().setAttribute("NOTES_SESSION", notes);
}
notes.add(note);
request.getSession().setAttribute("NOTES_SESSION", notes);
return "redirect:/home";
}
@GetMapping("/home")
public String home(Model model, HttpSession session) {
List<String> notes = (List<String>) session.getAttribute("NOTES_SESSION");
model.addAttribute("notesSession", notes!=null? notes:new ArrayList<>());
return "home";
}
@PostMapping("/invalidate/session")
public String destroySession(HttpServletRequest request) {
//invalidate the session , this will clear the data from configured database (Mysql/redis/hazelcast)
request.getSession().invalidate();
return "redirect:/home";
}
}
为了验证,我们可以创建一个html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Spring Boot Session Management Example</title>
</head>
<body>
<div>
<form th:action="@{/addNote}" method="post">
<textarea name="note" cols="40" rows="2"></textarea>
<br> <input type="submit" value="Add Note" />
</form>
</div>
<div>
<form th:action="@{/invalidate/session}" method="post">
<input type="submit" value="Destroy Session" />
</form>
</div>
<div>
<h2>Notes</h2>
<ul th:each="note : ">
<li th:text="">note</li>
</ul>
</div>
</body>
</html>
在页面上添加note到session中后,数据库中会创建两个表:
- spring_session
- spring_session_attributes
点击Destroy Session后,数据库中spring_session_attributes的数据将被清除。