前後端分離跨域處理
我們的項目已經處于前後端分離狀态了,那麼前後端分離狀态和我們之前的狀态有什麼差別的呢?
- 不分離:前端頁面看到的都是由後端控制,由後端渲染頁面或重定向,後端需要控制前端的展示,前端與後端的耦合度很高。
- 比如我們之前都是使用後端來執行重定向操作或是使用Thymeleaf來填充資料,而最終傳回的是整個渲染好的頁。

- 分離:後端僅傳回前端所需的資料,不再渲染HTML頁面,不再控制前端的效果。
- 至于前端使用者看到什麼效果,從後端請求的資料如何加載到前端中,都由前端通過JS等進行動态資料填充和渲染。
- 這樣後端隻傳回JSON資料,前端處理JSON資料并展示,這樣前後端的職責就非常明确了。
實作前後端分離有兩種方案,一種是直接放入SpringBoot的資源檔案夾下,但是這樣實際上還是在依靠SpringBoot内嵌的Tomcat伺服器進行頁面和靜态資源的發送,我們現在就是這種方案。
另一種方案就是直接将所有的頁面和靜态資源單獨放到代理伺服器上(如Nginx),這樣我們後端伺服器就不必再處理靜态資源和頁面了,專心傳回資料即可。
而前端頁面就需要通路另一個伺服器來擷取,雖然邏輯和明确,但是這樣會出現跨域問題,實際上就是我們之前所說的跨站請求僞造,為了防止這種不安全的行為發生,是以對異步請求會進行一定的限制。
這裡,我們将前端頁面和後端頁面直接分離進行測試,在登陸時得到如下錯誤:
Access to XMLHttpRequest at 'http://localhost:8080/api/auth/login' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
可以很清楚地看到,在Ajax發送異步請求時,我們的請求被阻止,原因是在響應頭中沒有包含Access-Control-Allow-Origin,也就表示,如果服務端允許跨域請求,那麼會在響應頭中添加一個Access-Control-Allow-Origin字段,如果不允許跨域,就像現在這樣。那麼,什麼才算是跨域呢:
- 請求協定如http、https不同
- 請求的位址/域名不同
- 端口不同
因為我們現在相當于前端頁面通路的是靜态資源伺服器,而後端資料是由我們的SpringBoot項目提供,它們是兩個不同的伺服器,是以在垮伺服器請求資源時,會被判斷為存在安全風險。
但是現在,由于我們前後端是分離狀态,我們希望的是能夠實作跨域請求,這時我們就需要添加一個過濾器來處理跨域問題:
@Bean
public CorsFilter corsFilter() {
//建立CorsConfiguration對象後添加配置
CorsConfiguration config = new CorsConfiguration();
//設定放行哪些原始域,這裡直接設定為所有
config.addAllowedOriginPattern("*");
//你可以單獨設定放行哪些原始域 config.addAllowedOrigin("http://localhost:2222");
//放行哪些原始請求頭部資訊
config.addAllowedHeader("*");
//放行哪些請求方式,*代表所有
config.addAllowedMethod("*");
//是否允許發送Cookie,必須要開啟,因為我們的JSESSIONID需要在Cookie中攜帶
config.setAllowCredentials(true);
//映射路徑
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", config);
//傳回CorsFilter
return new CorsFilter(corsConfigurationSource);
}
這樣,我們的SpringBoot項目就支援跨域通路了,接着我們再來嘗試進行登陸,可以發現已經能夠正常通路了,并且響應頭中包含了以下資訊:
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:63342
Access-Control-Expose-Headers: *
Access-Control-Allow-Credentials: true
可以看到我們目前通路的原始域已經被放行了。
但是還有一個問題,我們的Ajax請求中沒有攜帶Cookie資訊,這裡我們稍微改一下,不然我們的請求無法确認身份:
function get(url, success){
$.ajax({
type: "get",
url: url,
async: true,
dataType: 'json',
xhrFields: {
withCredentials: true
},
success: success
});
}
function post(url, data, success){
$.ajax({
type: "post",
url: url,
async: true,
data: data,
dataType: 'json',
xhrFields: {
withCredentials: true
},
success: success
});
}
添加兩個封裝好的方法,并且将withCredentials開啟,這樣在發送異步請求時,就會攜帶Cookie資訊了。
在學習完成Linux之後,我們會講解如何在Linux伺服器上部署Nginx反向代理伺服器。