1、前后端不分离情况
在处理session过程中,如果前后端项目在一个容器中,session是可以被获取的。例如如下项目结构:
结构
后端的代码是基本的设置值、获取值、销毁值的内容:
运行结果
由此可见,在前后统一的项目中,session通道不会直接断掉,除非是在关闭浏览器或者session超时后才会变化。
2、前后端分离情况
结构
将对应的session_demo.html放到了前端的项目当中
运行结果(因安全策略,跨域错误)
这里对三个跨域请求的后台设置允许跨域的请求头即可。
跨域运行后获取的Session不一致
也会导致其他按钮使用服务时产生新的通道:
3、原因与解决思路
问题原因
Session的工作原理:当用户首次访问服务器时,服务器会创建一个session,并生成一个唯一的session ID。这个ID通常存储在cookie中,并随请求一起发送回客户端。后续的请求中,客户端将携带这个session ID,服务器通过这个ID来识别用户的会话,并保持状态。
1、Session 是一种服务器端的存储方式,用于存储用户的状态信息。它允许服务器在多个页面请求或访问周期中保持状态。在 HTTP 协议中,默认是无状态的,意味着每次请求都是独立的,服务器不保留任何关于客户端的信息。Session 机制通过在服务端维护状态信息,使得服务器能够在多次请求之间识别同一个客户端,当 Session 超时或被显式销毁时,服务器会停止跟踪用户的状态。如果用户关闭浏览器,客户端的 Cookie 可能会丢失,但服务器端的 Session 数据可能仍然存在,直到超时或被服务器清理。
2、在前后端分离的架构中,前端发起请求和服务端响应确实涉及到多个独立的HTTP请求,因为每次HTTP请求都是无状态的。因此该demo中也是出现了每次访问sessionId不一致的情况。
可以配置为将session ID存储在cookie中,并随每个请求发送。这样,即使请求是独立的,服务器也能够通过session ID来识别和维持用户的会话状态。
解决思路
我们需要通过Cookie来帮助我们解决前后端分离时session不一致的问题。
解决方法
每次使用session时在头部中携带cookie信息,用于保证每次请求和响应都通过cookie携带的sessionId找到对应的Session。
操作步骤
1、我们在前端进行请求的时候添加以下内容,意味传输的时候携带Cookie信息
$.ajax({
...
//新增 对cookie的携带
xhrFields: {
withCredentials: true
},
...
})
2、后端需要设置对应的跨域ip,以及同意携带cookie的方法
@WebServlet("/setSession")
public class SetSessionServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取session
HttpSession session = req.getSession();
String user = req.getParameter("user");
//新增 限制的访问地址
String host = "http://localhost:5500";
resp.setHeader("Access-Control-Allow-Origin",host);
//新增 允许携带cookie
resp.setHeader("Access-Control-Allow-Credentials","true");
resp.setContentType("text/html;charset=UTF-8");
if (user == null){
resp.getWriter().println("session未存放数据!");
}else {
//session中设置属性
session.setAttribute("user",user);
resp.getWriter().println("session已存放数据,sessionId为:"+req.getSession().getId()); //获取session的唯一id
}
}
}
4.优化后运行结果
5、附件
前端项目代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5500 前端</title>
</head>
<body>
<button id="getSession" onclick="getSession()">获取session</button>
<button id="setSession" onclick="setSession()">存放session</button>
<button id="rmSession" onclick="removeSession()">移除session</button>
<script src="./js/jQuery-3.7.1.js"></script>
<script>
function getSession() {
$.ajax({
url: 'http://localhost:8081/Java_Web_Servlet_war_exploded/getSession',
//新增 对cookie的携带
xhrFields: {
withCredentials: true
},
method: 'GET',
success: function (resp) {
alert(resp)
}
})
}
function setSession() {
$.ajax({
url: 'http://localhost:8081/Java_Web_Servlet_war_exploded/setSession',
//新增 对cookie的携带
xhrFields: {
withCredentials: true
},
data: { 'user': 'admin' },
method: 'POST',
success: function (resp) {
alert(resp)
}
})
}
function removeSession() {
$.ajax({
url: 'http://localhost:8081/Java_Web_Servlet_war_exploded/removeSession',
//新增 对cookie的携带
xhrFields: {
withCredentials: true
},
method: 'GET',
success: function (resp) {
alert(resp)
}
})
}
</script>
</body>
</html>
后端项目结构:
后端代码-1:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/getSession")
public class getSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取session
HttpSession session = req.getSession();
String user = (String) session.getAttribute("user");
String host = "http://localhost:5500";
resp.setHeader("Access-Control-Allow-Origin",host);
resp.setHeader("Access-Control-Allow-Credentials","true"); resp.setContentType("text/html;charset=UTF-8");
if (user == null) {
resp.getWriter().println("你的session没有存放数据!");
} else {
resp.getWriter().println("sessionId为"+session.getId()+",存放的数据为:" + user);
}
}
}
后端代码-2:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/setSession")
public class SetSessionServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取session
HttpSession session = req.getSession();
String user = req.getParameter("user");
String host = "http://localhost:5500";
resp.setHeader("Access-Control-Allow-Origin",host);
resp.setHeader("Access-Control-Allow-Credentials","true");
resp.setContentType("text/html;charset=UTF-8");
if (user == null){
resp.getWriter().println("session未存放数据!");
}else {
//session中设置属性
session.setAttribute("user",user);
resp.getWriter().println("session已存放数据,sessionId为:"+req.getSession().getId()); //获取session的唯一id
}
}
}
后端代码-3:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/removeSession")
public class RemoveServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = (String)req.getSession().getAttribute("user");
req.getSession().removeAttribute("user");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/hml;charset=UTF-8");
String host = "http://localhost:5500";
resp.setHeader("Access-Control-Allow-Origin",host);
resp.setHeader("Access-Control-Allow-Credentials","true");
resp.getWriter().println("你的sessionId是:"+req.getSession().getId()+",移除了user:"+username);
}
}