当前位置: 首页 > news >正文

解决前后端分离跨域产生的session丢失问题

目录

前言

存储用户信息的方式

Cookies:

Token(令牌):

LocalStorage/SessionStorage:

Session:

Redis:

OAuth/OIDC:

本篇文章主要讲使用session会话来存储信息

会话机制

1. 何为一次会话,会话从什么时候开始,从什么时候结束?

2.cookies如何保持会话,它的工作流程?

3.什么是Session?

Session的工作原理:

问题出现

解决方法

总结


前言

现在大部分项目都采用的前后端分离,比如后端用spring boot,SSM ,前端用vue等。那么就有一个问题存在,一般用户登录过后,后面的操作会根据当前登录的用户id进行操作,所以说,我们需要将当前用户的信息(或者说id)进行存储

存储用户信息的方式

  1. Cookies

    传统的Web应用中,Cookies是存储用户会话信息的一种方式。服务器在用户登录后设置一个Cookie,包含用户ID或者其他标识符,然后发送给客户端。客户端在随后的每个请求中都会发送这个Cookie,服务器通过解析Cookie来识别用户。

  2. Token(令牌)

    在现代的Web应用中,尤其是RESTful API和单页面应用(SPA)中,Token是一种常见的身份验证机制。用户登录后,服务器会生成一个Token(如JWT - JSON Web Tokens),然后返回给客户端。客户端在随后的请求中将这个Token放在HTTP请求的头部(通常是Authorization字段)中。服务器通过解析Token来验证用户身份。

  3. LocalStorage/SessionStorage

    对于前端应用,LocalStorage和SessionStorage是两种在浏览器端存储数据的方式。它们可以用来存储用户的一些信息,如Token。LocalStorage存储的数据没有过期时间,而SessionStorage存储的数据在页面会话结束时会被清除。这些存储方式通常与Token结合使用。

  4. Session

    尽管在前后端分离的架构中使用Session不如在传统的Web应用中常见,但Session仍然可以作为一种服务器端的存储机制。用户登录后,服务器创建一个Session,并将其ID发送给客户端(通常是作为Cookie)。客户端在随后的请求中发送这个Session ID,服务器通过Session ID来识别和检索用户的会话信息。

  5. Redis

    许多现代应用使用Redis这样的内存数据存储来管理用户会话。用户登录后,服务器将用户信息存储在Redis中,并关联一个唯一的会话ID。客户端存储这个会话ID,并在随后的请求中发送它。服务器通过会话ID从Redis中检索用户信息。

  6. OAuth/OIDC

    对于需要第三方认证的应用,OAuth 2.0和开放ID连接(OIDC)提供了一种授权框架,允许用户使用第三方服务(如Google、Facebook)进行身份验证。这些服务在用户授权后会返回一个访问令牌,应用可以使用这个令牌来获取用户信息。

本篇文章主要讲使用session会话来存储信息

会话机制

session和cookies常用来会话保持。

1. 何为一次会话,会话从什么时候开始,从什么时候结束?

一次会话是指: 好比打电话,当A打给B,电话接通了 会话开始,持断会话结束。 浏览器访问服务器,就如同打电话,浏览器A给服务器发送请求,访问web程序,该次会话就开始,其中不管浏览器发送了多少请求 ,都为一次会话,直到浏览器关闭,本次会话结束。

2.cookies如何保持会话,它的工作流程?

工作流程:

servlet创建cookie,保存少量数据,发送浏览器。
浏览器获得服务器发送的cookie数据,将自动的保存到浏览器端。
下次访问时,浏览器将自动携带cookie数据发送给服务器。

3.什么是Session?

想象一下,你去了一个图书馆,每次你进去,图书管理员会给你一个专属的储物柜,你可以把你的东西放进去。这个储物柜就像是你的“Session”。当你需要借书或者还书时,你只需要出示你的储物柜钥匙(Session ID),图书管理员就能帮你处理事务,而不需要每次都重新登记你的信息。

在计算机的世界里,Session就是服务器用来识别不同用户的一种方式,它帮助服务器记住用户的状态和行为。

Session的工作原理:
  1. 用户登录

    当你第一次访问网站并登录时,就像你第一次去图书馆,服务器需要确认你是谁。你输入用户名和密码,服务器验证这些信息。
  2. 创建Session

    登录成功后,服务器会创建一个Session,这个Session就像是一个储物柜,里面可以存放你的用户信息,比如用户ID、权限、购物车内容等。
  3. 分配Session ID

    服务器会生成一个唯一的Session ID,就像你的储物柜钥匙。这个ID是一串数字和字母的组合,很难被猜到。
  4. 存储Session ID

    服务器会将这个Session ID发送给你的浏览器,浏览器通常会把它存储在Cookie中。Cookie就像是你把钥匙放在口袋里,每次你回到图书馆(网站),你的钥匙(Session ID)都会自动展示给图书管理员(服务器)。
  5. 使用Session

    每次你向服务器发送请求时,浏览器都会在你的请求中包含这个Session ID。服务器收到请求后,就能通过Session ID找到你的储物柜(Session),并获取你的用户信息。
  6. 结束Session

    当你完成操作,比如注销登录或者关闭浏览器时,你的Session可以被关闭。这就像是你离开图书馆时,图书管理员帮你清空储物柜,准备给下一个用户使用。

问题出现

由于前后端分离的原因,会产生跨域问题,既然是跨域,每次前端访问后台时,都以不同的主机去访问,那么每个主机分配的Session ID也就不同,后台获取不到登录记录的Session ID,也就认为没有登录。

解决方法

1.在springmvc.xml中进行配置,开启  springMvc 自带的跨域配置

<mvc:cors><mvc:mapping path="/**"allowed-origins="http://localhost:5173"allowed-methods="POST, GET, OPTIONS, DELETE, PUT"allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"allow-credentials="true" /></mvc:cors>

2.配置一个跨域管理器

package org.bo.config;import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/*** @author qinbo* @version 1.0* @description: CORS Filter with SameSite attribute* @date 2024/12/10 21:11*/
public class CORSFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;// 设置允许的源httpResponse.setHeader("Access-Control-Allow-Origin", "http://localhost:5173");// 允许携带凭证httpResponse.setHeader("Access-Control-Allow-Credentials", "true");// 允许的方法httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");// 允许的头部httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");// 处理预检请求if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {httpResponse.setStatus(HttpServletResponse.SC_OK);} else {chain.doFilter(request, response);}// 设置 SameSite 属性String cookieHeader = httpResponse.getHeader("Set-Cookie");if (cookieHeader != null) {// 添加 SameSite=None; Secure 如果需要httpResponse.setHeader("Set-Cookie", cookieHeader + "; SameSite=None; Secure");}}@Overridepublic void destroy() {}
}

在web.xml进行注册

<filter><filter-name>CORSFilter</filter-name><filter-class>org.bo.config.CORSFilter</filter-class></filter><filter-mapping><filter-name>CORSFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

3.前端配置

我是用vue  axios 发送的请求

只需要在main.js 中配置如下代码

axios.defaults.withCredentials=true//允许跨域 时携带cookie

即可解决跨域问题产生的sessionid不一致问题

总结

一般存储用户信息通过token,jwt令牌再使用缓存机制redis进行存储,但目前的项目是个小实验,就直接用session+ThreadLocal进行存储即可。

写在最后
如果你觉得有帮助到你,请给博客点个赞和收藏,让更多的人看到呀~

也欢迎你关注我


http://www.mrgr.cn/news/79695.html

相关文章:

  • 【云计算】虚拟化技术
  • 微信小程序base64图片与临时路径互相转换
  • 淘宝详情网页爬虫:技术解析与实战指南
  • 简述框架和函数库的区别
  • Atlas学习笔记(1)—— 基础入门
  • android 常用三方框架
  • 一个直接看央视频道的软件,可直接安装到TV
  • DMA代码部分
  • 计算机网络基础知识
  • 基于python+django+vue的购物商城系统
  • 雪花算法详解
  • 正则表达式的高级方法
  • STL之空间配置器allocator
  • 正则化:机器学习中的泛化利器
  • webrtc-java:引领Java进入实时通信新时代
  • 线上常见问题案例及排查工具
  • DevOps持续集成
  • STM32-C语言基础知识
  • 力扣HOT 100(图)
  • 多人聊天室 NIO模型实现
  • 1.1.Flink的项目初始化和Hello-world
  • 在Ubuntu22.04 jammy下用qemu模型riscv32环境装鸿蒙(未完成,待续)
  • PDF处理的创新工具:福昕低代码平台尝鲜
  • leecode中的面试100题
  • 【推荐算法】单目标精排模型——DIN
  • 阿里云ack部署rabbitmq集群