前後端分離之後,請求跨域無法傳遞cookie的問題,最近在做公司一個小項目時遇到坑,記錄一下下
前言
那一天是我畢業後工作生涯的第30天,第一次接觸前後端分離開發,我感覺好像,慢慢領悟到了前後端分離開發的真諦:或許大概可能也許是前後端甩鍋開發
場景一
前臺瘋狂的點擊頁面,發送請求,但是後臺服務器總是沒有迴應,後臺接口雖打了斷點,但是根本進不到斷點處。。。
前端:我請求發過去了,數據格式也是對的,你接口文檔就是那樣寫的,我按照接口文檔要求寫的,你服務器怎麼了,你接口寫的對嗎,巴拉巴拉。。。。
後臺:我接口文檔寫的很對欸,我這邊postman測試可以的,我測試通過了才寫的文檔欸,你那邊什麼情況啊,你發送的請求對嗎,巴拉巴拉。。。
場景二
前臺登陸的時候,驗證碼一直校驗不通過
前端:我輸入的驗證碼,就是圖片中的驗證碼,爲什麼你後臺一直校驗不通過啊,怎麼肥四啊,你後臺接口寫的對嗎,邏輯判斷的對嗎,巴拉巴拉。。。。
後臺:肯定對啊,我這邊我自己用postman已經測試通過了,你那邊怎麼搞的,我後臺都獲取不到你的 session 欸,巴拉巴拉。。。
跨域問題
場景一
就是典型的跨域問題,在前後端分離開發的時候,由於前後臺代碼不在一臺服務器上了,前端頁面服務器想要訪問後臺接口的時候,由於瀏覽器的 同源策略,會拒絕掉這些訪問,導致後臺根本收不到這些請求;
後臺需要配置下;
/**
* 處理跨域問題
*/
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 1允許服務端訪問
corsConfiguration.addAllowedOrigin("*");
// 1.1允許本地訪問
corsConfiguration.addAllowedOrigin("http://localhost:8032");
// 2允許任何頭
corsConfiguration.addAllowedHeader("*");
// 3允許任何方法(post、get等)
corsConfiguration.addAllowedMethod("*");
// 4 允許withCredentials報文頭
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
最簡單粗暴的,來自任何源的請求都接收;
cookie問題
跨域訪問的時候,瀏覽器默認是不帶cookie去的,這樣導致每次後臺都產生根據請求產生新的session,驗證碼值保存在各自的session裏面,當然也就永遠的檢驗不通過了!
前臺在發送 Ajax 請求的時候,告訴瀏覽器允許跨域帶 cookie ,(這是坑請注意。。。)寫上如下;
$.ajax({
type: "POST",
url: serverPath + "/api/v1/login",
contentType: 'application/x-www-form-urlencoded;charset=utf-8',
data: {username:$("#username").val(), password:$("#password").val(), rememberMe},
dataType: "json",
xhrFields: {
withCredentials: true //攜帶跨域cookie
},
success: function(data){
if(data.code == 200){
layer.msg(data.msg);
window.location.href="index.html";
}else{
layer.msg(data.msg);
}
},
})
攔截器導致的跨域問題
上面的問題都解決以後,最後給系統加上攔截器。跨域問題又來了。
我們需要在攔截器裏面放行 options 方法,此方法是瀏覽器發出來的探測方法,探測目標主機是否允許跨域,結果在探測的時候,被攔截器攔截了,送出去的偵察兵音信全無,瀏覽器就不會向目標主機發送請求了,發出一個 cros 跨域錯誤
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
/**
* 在訪問controller前判斷是否登錄,返回json,不進行重定向。
* @param request
* @param response
* @return true-繼續往下執行,false-該filter過濾器已經處理,不繼續執行其他過濾器
* @throws Exception
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (request instanceof HttpServletRequest) {
if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
return true;
}
}
return super.isAccessAllowed(request, response, mappedValue);
}
}
後記
多年以後,或許我說的最多的話就是:
- 我這邊能用
- 在我這是好使的
- postman測試可以通過
- 你沒清緩存吧