解决SpringBoot+Vue跨域SessionID不一致的问题

前言

最近做毕业设计项目的时候,要做图片验证码这个功能,设计方案需要用到SessionID这个东西。

项目是先开发的接口,使用Postman测试的时候用的好好的,都是一个SessionId。

结果开始编写前端代码的时候,每个请求的SessionID都不一样,翻遍网上的教程步骤也解决不了,今天突然开窍找到了解决方法。

前端

前端使用的是axios发送的请求,需要设置axios.defaults.withCredentials = true来传递cookie,例如:

1
2
3
4
5
6
7
import axios from 'axios'
// 全局设置请求带cookie(必须)
axios.defaults.withCredentials = true
// 全局设置请求带token请求头(自定义)
axios.defaults.headers.common['token'] = localStorage.getItem("token");
// 全局设置API地址(自定义)
axios.defaults.baseURL = 'http://127.0.0.1:9001'

后端

后端就稍微有些复杂,首先需要设置跨域,然后还要设置服务端发送的Cookie能够跨站点使用。

本篇文章的跨域是用拦截器实现的,整合代码如下:

application.yml

在配置文件中添加如下配置

1
2
3
4
5
6
server:
servlet:
session:
cookie:
# 是否总是将会话 cookie 标记为安全。
secure: true

跨域拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Log4j2
public class CrossInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("SessionId:" + request.getSession().getId());

// 表示接受任意域名的请求,也可以指定域名
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
// 该字段可选,是个布尔值,表示是否可以携带cookie
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT,PATCH, DELETE, OPTIONS");
// 允许前端传递的请求头参数(按需手动添加)
response.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With, Accept, Authorization, token, Responsetype");
response.setHeader("Access-Control-Max-Age", "3600");

if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
return true;
}
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

启用拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import cn.insectmk.chatbotweb.interceptor.CrossInterceptor;
import org.apache.tomcat.util.http.Rfc6265CookieProcessor;
import org.apache.tomcat.util.http.SameSiteCookies;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/**
* 设置Cookie的SameSite
*/
@Bean
public TomcatContextCustomizer sameSiteCookiesConfig() {
return context -> {
final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
cookieProcessor.setSameSiteCookies(SameSiteCookies.NONE.getValue());
context.setCookieProcessor(cookieProcessor);
};
}

/**
* 向容器中添加跨域验证拦截器
* @return
*/
@Bean
public CrossInterceptor crossInterceptor() {
return new CrossInterceptor();
}

/**
* 拦截规则
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 跨域拦截规则
registry.addInterceptor(crossInterceptor())
.addPathPatterns("/**");
}
}

重启项目,重新使用前端访问接口,看sessionID是否一致:

1
2
3
4
5
2024-03-09 15:14:29.453  INFO 6072 --- [.1-9001-exec-10] c.i.c.interceptor.CrossInterceptor: SessionId:512D7A220642FCAD61E730752546A37F
2024-03-09 15:14:29.630 INFO 6072 --- [0.1-9001-exec-9] c.i.c.interceptor.CrossInterceptor: SessionId:512D7A220642FCAD61E730752546A37F
2024-03-09 15:14:29.788 INFO 6072 --- [0.1-9001-exec-1] c.i.c.interceptor.CrossInterceptor: SessionId:512D7A220642FCAD61E730752546A37F
2024-03-09 15:14:29.949 INFO 6072 --- [0.1-9001-exec-2] c.i.c.interceptor.CrossInterceptor: SessionId:512D7A220642FCAD61E730752546A37F
2024-03-09 15:14:30.164 INFO 6072 --- [0.1-9001-exec-3] c.i.c.interceptor.CrossInterceptor: SessionId:512D7A220642FCAD61E730752546A37F

参考文章

springboot-vue前后端分离项目跨域session不一致的问题

Springboot JSESSIONID 设置 SameSite 属性为 NONE