项目场景:
记录一下今天在进行java全栈学习的过程中出现的问题
问题描述
前后端都设置了
credentials
为true
,但是同一个浏览器每次访问服务端都无法获取并携带到相同cookie
到服务端。
后来延伸出另一个问题,通过yml
配置文件可以轻松解决,但是不能通过配置类解决这个问题。后来把重心转移到如何对servlet
容器进行设置才引刃而解。
前端请求代码如下:
async sendWithConfig() {
const _axios = axios.create({ //创建请求配置
baseURL: 'http://127.0.0.1:8080',
withCredentials: true
});
const resp1 = await _axios.post('/api/post/session/set', {});
const resp2 = await _axios.post('/api/post/session/get', {});
console.log(resp1.data);
console.log(resp2.data);
}
java跨域配置如下:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost")
.maxAge(60000)
.allowCredentials(true)
.allowedHeaders("*")
.allowedMethods("*");
}
}
后端接口如下:
@PostMapping("/post/session/set")
public ResultVo<String> setSession(HttpSession httpSession) {
logger.info("{}", httpSession.getId());
httpSession.setAttribute("cookie", httpSession.getId());
return ResultVo.respWithoutData(ResultEnums.SUCCESS);
}
@PostMapping("/post/session/get")
public ResultVo<String> getSession(HttpSession httpSession) {
logger.info("{}", httpSession.getId());
logger.info("{}", httpSession.getAttribute("cookie"));
return ResultVo.respWithoutData(ResultEnums.SUCCESS);
}
原因分析:
浏览器在进行跨域访问的时候由于默认的
same-site
策略,导致浏览器无法接收第三方不信任的cookie,每次发起请求的时候也就无法携带相同cookie
到服务端,于是服务端每次都会生成新的cookie
返回。
解决方案:
除了在前后端中配置
credentials
以外,还要在后端配置类中配置same-site
和secure
方式一 ,通过配置类对servlet容器进行配置:
@Configuration
public class SameSiteConfig {
//对servlet容器进行配置,采用这种方式才可以把值设置到servlet容器中
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> webServerFactoryCustomizer() {
return factory -> {
Session.Cookie cookie = factory.getSession().getCookie();
cookie.setSameSite(Cookie.SameSite.NONE); //设置 SameSite 为 none,不依赖浏览器的same-site策略
cookie.setSecure(true); //还需要配置设置 secure 浏览器才能接收并携带相同cookie
};
}
}
方式二,通过yml配置文件对servlet进行配置:
server:
port: 8080
servlet:
context-path: /api
session:
cookie:
same-site: none
secure: true
验证:两次请求都是相同cookie