1. 程式人生 > >Ajax 跨域解決(一)——SpringBoot學習

Ajax 跨域解決(一)——SpringBoot學習

·

什麼是跨域

在目前的前後端分離開發模式下,前端使用 Ajax 訪問後端提供的介面獲取資料,產生報錯。

 

跨域發生的原因

1. 瀏覽器的限制

2. 發生跨域訪問

3. 傳送的是 XHR(XMLHttpRequst) 請求

三者同時發生,就會發生跨域問題

 

解決方式

因為是三者同時發生,才能發生跨域問題,因此針對三者,處理其中的一個即可。

 

首先是瀏覽器的限制,需要指定引數讓瀏覽器不做校驗,但方法不太合理,需要每個人都去做修改。其次是傳送的請求不要是 XHR 型別的,解決方式是 JSONP 。最後是針對跨域,分為兩點,一是讓被呼叫方支援跨域,在響應頭中新增引數,表示支援跨域訪問,核心是支援跨域,二是讓呼叫方在請求中使用代理,將從 A 域名傳送到 B 的請求通過代理,讓 B 認為是從本域名來的,核心是隱藏跨域。

 

具體解決方式

針對瀏覽器,通過命令列的方式啟動,讓其不要做跨域校驗即可。

1 eg:chrome --disable-web-security

 

 

 

針對 XHR 方式,本身瀏覽器傳送的是 json 請求,通過 jsonp 的方式,將其變為 js 的方式,核心是通過動態新增 script 的方式來封裝了請求,從而解決跨域問題。

 

使用這種方式需要修改服務端的程式碼,修改方式如下:

@ControllerAdvice

public class JsonpAdvice extends
AbstractJsonpResponseBodyAdvice ( public JsonpAdvice() { super("callback"); } }

 

 

前端通過制定 dataType 的方式來發送請求,如下所示

$.ajax({

    url:base+"/get1",

    dataType: "jsonp",

    jsonp: "callback",

    cache: true,

    type:"post",

    success:function(json){

        result 
= json; } })

 

但使用這種方式仍然是不好的方式,其有如下弊端

1. 需要伺服器端改變程式碼,如果涉及呼叫第三方介面,根本無法完成;

2. 只支援 GET 請求,在真是的業務場景中十分受限;

3. 因為改變了請求的型別,從 XHR 變為了 js 方式,因此 XHR 的很多優良特性無法使用。

 

因此,解決跨域問題最好的方式還是通過解決跨域訪問來解決,使用伺服器端支援跨域或呼叫端隱藏跨域來解決。

 

呼叫方解決跨域(支援跨域)的3種解決方式

1. 伺服器端實現

2. Nginx 配置

3. Apache 配置

 

使用 Filter 來實現

通過過濾器在所有請求的 Response 中新增欄位來支援跨域訪問。

 1 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
 2 
 3     HttpServletRequest req = (HttpServletRequest) request;
 4 
 5     HttpServletResponse res = (HttpServletResponse) response;
 6 
 7     String origin =req.getHeader("Origin");
 8 
 9     if (!StringUtils.isEmpty(origin)){ // 動態新增訪問地址,使得所有的域名都可以跨域訪問
10 
11         res.addHeader("Access-Control-Allow-Origin",origin);
12 
13     }
14 
15     String headers = req.getHeader("Access-Control-Request-Headers");
16 
17     if (!StringUtils.isEmpty(headers)){ // 動態新增自定義訪問頭
18 
19         res.addHeader("Access-Control-Allow-Headers",headers);
20 
21     }
22 
23     res.addHeader("Access-Control-Allow-Methods","*");
24 
25     res.addHeader("Access-Control-Max-Age","3600");
26 
27     res.addHeader("Access-Control-Allow-Credentials","true");
28 
29     chain.doFilter(request,response);
30 
31 }
32 
33 
34 
35 @Bean
36 
37 FilterRegistrationBean registrationBean(){
38 
39     FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean();
40 
41     filterRegistrationBean.addUrlPatterns("/*");
42 
43     filterRegistrationBean.setFilter(new CrosFilter());
44 
45     filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
46 
47     filterRegistrationBean.setName("Ajax");
48 
49     return filterRegistrationBean;
50 
51 }

 

 

 

 

被呼叫方解決跨域(隱藏跨域)的解決方式

在 Spring 框架中的解決方式:在需要的類或方法上加上註解, @CrossOrigin

 

Nginx 配置

Apache 配置

Nginx 和 Apache 的解決方式因為涉及到其兩個框架的方式,因為還沒有深入瞭解過,所以在這沒有敘述,以後深入學習過後,再詳細編寫。