以前写好的登录用的 SpringSession + SpringSecurity,突然登录功能不能用了。火狐以及手机上的浏览器等都没有问题,就谷歌浏览器有问题(直接在地址栏访问get接口也没有问题,但是每次 ajax 请求后台的时候,后台都会新创建一个 session,导致带权限的接口统统失效~~~~)
1、问题原因
2、解决方案(https)
@Bean
public CookieSerializer httpSessionIdResolver(){
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
cookieSerializer.setCookieName("token");
cookieSerializer.setUseHttpOnlyCookie(true);
cookieSerializer.setUseSecureCookie(true);
cookieSerializer.setSameSite("None;Secure");
return cookieSerializer;
}
重点是 cookieSerializer.setSameSite(“None;Secure”);
3、前端需要跨域访问
- ajax
crossDomain: true,
xhrFields: {
withCredentials: true
},
- 后台
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request=(HttpServletRequest)servletRequest;
// System.out.println(request.getSession().getId());
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "0");
response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
response.setHeader("Access-Control-Allow-Credentials", "true");
filterChain.doFilter(servletRequest,servletResponse);
}
4、效果实例
4.1、接口(设置session并获取session的值)
@RestController
@RequestMapping("/test1")
@CrossOrigin(origins = "*")
public class TestController {
@GetMapping("/get")
public Object get(HttpSession session){
Map<String, Object> result = new HashMap<>(4);
// 遍历
for (Enumeration<String> enumeration = session.getAttributeNames();
enumeration.hasMoreElements();) {
String key = enumeration.nextElement();
Object value = session.getAttribute(key);
result.put(key, value);
}
return result;
}
@GetMapping("/set")
public Object set(HttpSession session, @RequestParam("key") String key,@RequestParam("value") String value){
session.setAttribute(key,value);
return session.getId();
}
}
4.2、ajax 请求
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<!-- 引用jquery -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<body>
<button onclick="ajax1()">设置 session</button>
<button onclick="ajax2()">获取 session</button>
</body>
<script>
var URLS= "http://localhost:8080";
function ajax1() {
$.ajax({
url: URLS+ '/test1/set?key=keys&value=values',
type: "GET",
async: "false",
crossDomain: true,
xhrFields: {
withCredentials: true
},
success: function (data) {
console.log(data);
}
});
}
function ajax2() {
$.ajax({
url: URLS+ '/test1/get',
type: "GET",
crossDomain: true,
xhrFields: {
withCredentials: true
},
success: function (data) {
console.log(data);
}
});
}
</script>
</html>
4.3、设置 SameSite 之前(ajax 请求每次获取到的sessionId 都不一致)
但是直接在地址栏访问接口(每次获取到的 sessionId 一致)