集成SpringSession框架之后,axios无法带sessionId到服务器端

1 篇文章 0 订阅
1 篇文章 0 订阅

一、背景

在微服务中,为了实现Session共享,使用Spring Session框架将sesion信息存储到redis中,并自动进行序列化与反序列化。但是在前端的请求中,却发现无法使用Session,Session中获取的内容得不到

二、猜想与解决

  1. 初步判断两个请求的Session不是同一个,通过wireshark进行抓包,发现每次请求都没有带Cookie,同时服务器每次都使用Set-Cookie设置SESSION,同时带有了很多奇怪的Cookie属性
    cookieset-cookie

  2. 记忆中,以往传递SessionId都是通过JSESSIONID的Cookie,但这里服务器要求设置的却是SESSION,猜测Spring Session自定义了SessionId策略,然后对Cookie的那些参数进行了查询,具体意思如下:

    • httpOnly:防止XSS攻击,使得JS无法获取该Cookie
    • SameSite: 用于限制第三方网站请求携带Cookie的策略,具体可参考这里
    • Path: 访问该网站相同应用上下文时带上改Cookie,相当于指定ContextPath
  3. 根据以上查询,基本判断是因为更换的Cookie名称和httpOnly导致axios无法带上该Cookie来使用Session,于是查找Spring Session对Cookie中SessionId的读写,具体参考这里,于是知道是org.springframework.session.web.http.CookieSerializer接口负责,默认实现是org.springframework.session.web.http.DefaultCookieSerializer

    //org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration
	@PostConstruct
	public void init() {
		CookieSerializer cookieSerializer = (this.cookieSerializer != null) ? this.cookieSerializer
				: createDefaultCookieSerializer();
		this.defaultHttpSessionIdResolver.setCookieSerializer(cookieSerializer);
	}

	@Autowired(required = false)
	public void setCookieSerializer(CookieSerializer cookieSerializer) {
		this.cookieSerializer = cookieSerializer;
	}

  1. 由此代码可知,只需自定义一个CookieSerializer即可注入到该配置中替换默认配置,同时发现DefaultCookieSerializer提供属性设置,于是改法如下:
@Configuration
@EnableRedisHttpSession
public class MySessionAutoConfiguration {

    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setSameSite(null);
        // 重点在下面两个方法的调用,我将名字改为默认的JSESSIONID同时禁用HttpOnly
        serializer.setUseHttpOnlyCookie(false);
        serializer.setCookieName("JSESSIONID");
        serializer.setDomainName(null);
        return serializer;
    }
}

  1. 问题完美解决

三、axios跨域注意

  1. 若跨域时需要带上cookie,则需手动设置withCredentials=true
// 全局设置可以如下
import axios from "axios"
axios.defaults.withCredentials
// 如果是部分设置,则只需要在config中带上改属性即可,如
axios.get("/user/login",{withCredentials:true})
  1. 前端使用了withCredentials=true,则后端要进行允许,如下:
// 以下是Http响应头
Access-Control-Allow-Origin: localhost:8080 //这里需要是具体的请求传递过去的Origin头,不能是*
Access-Control-Allow-Credentials: true // 开启这里才能带上Cookie

四、参考

1.Cookie 的 SameSite 属性
2. SpringSession系列-sessionId解析和Cookie读写策略
3. Cookie中的httponly的属性和作用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果服务器端无法接受到 Axios 前端传递的 JSON 对象,可能是因为以下原因: 1. 前端没有将请求体设置为 JSON 格式的字符串。 确保在发送 POST 请求时,将请求体设置为 JSON 格式的字符串。可以使用 JSON.stringify() 方法将对象转换为 JSON 字符串。 ```javascript const data = { name: 'John', age: 25 }; axios.post('/api/users', JSON.stringify(data)) .then(response => { console.log(response.data); }) .catch(error => { console.error(error); }); ``` 2. 后端没有使用 body-parser 中间件来解析请求体中的 JSON 数据。 在服务器端,必须使用 body-parser 中间件来解析请求体中的 JSON 数据。确保在服务器端使用以下代码: ```javascript const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); app.post('/api/users', (req, res) => { const data = req.body; console.log(data); // Handle the data... }); app.listen(3000, () => { console.log('Server is running on port 3000'); }); ``` 3. 请求头中的 Content-Type 不是 application/json。 在发送 POST 请求时,确保请求头中的 Content-Type 设置为 application/json。可以使用 Axios 的默认配置或者手动设置请求头。 默认配置: ```javascript axios.defaults.headers.post['Content-Type'] = 'application/json'; ``` 手动设置: ```javascript axios.post('/api/users', JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } }) ``` 如果以上方法都无法解决问题,则可能是其他原因导致的。可以在控制台查看请求和响应的详细信息,以便进一步分析和解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值