前後端分離中Cors跨域問題解決方法總結

序言

        目前項目開發流行前後端分離,前後分離勢必會出現CORS問題了。CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。本文主要討論前後端分離之後對於Cors問題的解決方案。需要說明的是本文章前端使用Angular9,後端使用的是SpringBoot 2.1.3.RELEASE。

一、場景

        前端發起請求主要關注JSON形式和JSONP形式。

1.1 JSON數據請求場景

        前端請求代碼實現形式,這裏使用的是HttpClientModule。

```

doPost() {
  const url = `http://localhost:8080/interface/testPost`;
  const httpOptions =  {
    headers: new HttpHeaders({'Content-Type': 'application/json'})
  };
  this.httpClient.post(url,{"username":"張三丰","age":45}, httpOptions).subscribe( (response) => {
    console.log(response);
    this.masterInfo = response;
  });
}

```

後端SpringBoot應用解決Json數據請求的跨域問題有多種:

1、使用@CrossOrigin註解來實現跨域,使用註解可以以最細粒度控制可跨域範圍,此註解可添加在Controller類上和方法上,Spring Framework 4.2開始支持此註解。

2、CORS全局配置一個CorsConfigure類實現WebMvcConfigure接口或者繼承WebMvcConfigurerAdapter類,形式都是一樣,都是給CorsRegistry 設置跨域允許的請求源:

```

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .maxAge(3600)
                .allowCredentials(true);
    }

```

3、實現Filter接口自定義一個允許跨域的過濾器

```

@WebFilter(urlPatterns = "/*")
public class CorsFilter implements Filter {
 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,
            ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin","*");
        filterChain.doFilter(request, servletResponse);
    }
 
    @Override
    public void destroy() {
 
    }
 
    @Override
    public void init(FilterConfig arg0) throws ServletException {
 
    }
}

```

1.2 JSONP數據請求場景

        這需要說明一下瀏覽器的特性,瀏覽器不允許頁面中的腳本程序跨域讀取數據,但卻允許HTML引用跨域的資源,如圖片,CSS和腳本程序。對於腳本程序的引用比較特殊,它被瀏覽器解析以後,就和本地的腳本程序別無二致且可立即進行解釋並執行。

前端JSONP請求需要用到的依賴HttpClientJsonpModule。請求實現方式是使用HttpClient發起jsonp請求。

```

  getJSONP() {
    /* jsonp請求,需要服務器支持才行 */
    const url = `http://localhost:8080/interface/testJSONP`;
    this.httpClient.jsonp(url, "CallBack").subscribe((response: any) => {
      console.log(response);
      console.log(response.master);
    });
  }

```

服務器端接口對應的實現方式,這裏使用的JSONObject是阿里的fastjson

```

    @RequestMapping("/testJSONP")
    @ResponseBody
    public String testJSONP(@RequestParam("CallBack") String callback) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("result","200");
        jsonObject.put("master","charberming");
        jsonObject.put("appname","app1");
        return callback+"("+jsonObject+")";  
    }

```

        這裏返回的數據必須是由前端請求url上帶着的callback參數拼接的json字符串格式,否則前端會報錯。在這裏由於我們在前端請求參數中設置的回調參數爲CallBack,所以在服務端程序中,我們要拿到的參數也是CallBack,保持一致。

        注:主要是在學習angular過程中,出現跨域問題,網上找的辦法主要是在前端設置,比如說angular設置代理文件啓動,還有說使用nginx反向代理,前者說是能解決跨域問題,但是後者就太扯淡了,但還是都去驗證了下,沒成功。因此在這裏做一些總結,以節省道友時間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章