原因:最近在将一个项目修改为前后端分离中,前端使用Vue 开发碰到跨域问题,这里记录一下。
服务器端修改
1、在配置类中设置 CorsFilter,新建CorsConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig{
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
// 允许cookies跨域
config.setAllowCredentials(true);
// 允许向该服务器提交请求的URI,*表示全部允许。。这里尽量限制来源域,比如http://xxxx:8080
// ,以降低安全风险。。
config.addAllowedOrigin("*");
// 允许访问的头信息,*表示全部
config.addAllowedHeader("*");
// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
config.setMaxAge(18000L);
// 允许提交请求的方法,*表示全部允许,也可以单独设置GET、PUT等
config.addAllowedMethod("*");
/*
* config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET");//
* 允许Get的请求方法 config.addAllowedMethod("PUT");
* config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE");
* config.addAllowedMethod("PATCH");
*/
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
2、修改 Spring Security配置,加上cors()来开启跨域以及requestMatchers(CorsUtils::isPreFlightRequest).permitAll()来处理跨域请求中的preflight请求。
//开启跨域 cors()
http.cors().
and().csrf().disable().
authorizeRequests().
//处理跨域请求中的Preflight请求
requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
注:前两步服务器端就已经开启跨域访问了,但是在实际测试中发现,前端访问session一直会发生变化,翻了大量文章后发现spring-session 2.x 中 Cookie里面居然引入了SameSite,他默认值是 Lax。
SameSite Cookie 是用来防止CSRF攻击,它有两个值:Strict、Lax
SameSite = Strict:
意为严格模式,表明这个cookie在任何情况下都不可能作为第三方cookie;
SameSite = Lax:
意为宽松模式,在get请求是可以作为第三方cookie,但是不能携带cookie进行跨域post访问(这就很蛋疼了,我们那个校验接口就是POST请求);
总结:
前端请求到后台,每次session都不一样,每次都是新的会话,导致获取不到用户信息,添加配置取消仅限同一站点设置。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
@Configuration
public class SpringSessionConfig {
@Bean
public CookieSerializer httpSessionIdResolver() {
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
// 取消仅限同一站点设置
cookieSerializer.setSameSite(null);
return cookieSerializer;
}
}
前端修改
Vue在公共js中添加统一配置
使用Vue.resource发送请求时配置如下:
Vue.http.options.xhr = { withCredentials: true };
Vue.http.interceptors.push((request, next) => {
request.credentials = true
next()
})
其他工具配置,可以参考如下配置,未测试;
使用Vue.axios发送请求时配置如下:
axios.defaults.withCredentials = true;
jquery请求带上 xhrFields: {withCredentials: true}, crossDomain: true;
$.ajax({
type: "post",
url: "",
xhrFields: {withCredentials: true},
crossDomain: true,
data: {username:$("#username").val()},
dataType: "json",
success: function(data){ }
});
参考:
https://www.cnblogs.com/zimublog/p/10786110.html
https://blog.csdn.net/qq_17555933/article/details/92017890
https://www.cnblogs.com/yuarvin/p/10923280.html