原因:最近在將一個項目修改爲前後端分離中,前端使用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