前端-關於CORS跨域的解決方案,面向服務端
最近自己在寫後臺管理系統的時候,並沒有采用jsp、freemaker、葉子等模板技術,而是由後端提供數據api,前端通過AJAX和JQuery來動態操作頁面上的一些div、table元素,從而實現報表的動態加載。
因為本人並非專業前端,所以采用的技術比較古老,對於最近的前端框架,vue,angular,react等等,暫且按下不表。
說說遇到的幾個坑:
1、AJAX發送請求的時候,默認是異步的,而不是同步的。
基於低耦合的編碼,我在寫ajax時,數據請求和數據處理是分開的,沒加同步執行就導致了我的請求發送後,沒有拿到回調的數據就已經開始執行數據處理了。
2、關於非同源鏈接發送異地址的請求,也就是CORS,跨域問題。
瀏覽器出於安全考慮,限制了JS發起跨站請求,使用XHR對象發起請求必須遵循同源策略(SOP:Same Origin Policy),跨站請求會被瀏覽器阻止,這對開發者來說是很痛苦的一件事,尤其是要開發前後端分離的應用時。
在現代化的Web開發中,不同網絡環境下的資源數據共享越來越普遍,同源策略可以說是在一定程度上限制了Web API的發展。
關於跨域問題,只要用ajax來發送請求都會遇到。上個月一直在做一個小程序應用的後端服務接口,前端的朋友並沒有和我放映有跨域問題,估計是小程序底層做了比較良好的封裝,或者底層並不是使用簡單的ajax請求,從而規避了這個問題。
前端如果解決的話,無非就是jsonp,加請求頭,但是這樣會增加前端同事的工作量。
我的解決方案是在後端解決:
(1)最簡陋的方法,在後端web中添加一個filter,這個filter要的過濾順序放在最前面,將對應的HTTP請求加上一個請求頭。
1 /** 2 * 解決跨域問題 3 * Created by huxingyue on 2017/8/31. 4 */ 5 @WebFilter(filterName = "CORSFilter") 6 public class CORSFilter implements Filter { 7 public void destroy() { 8 } 9 10 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throwsServletException, IOException { 11 HttpServletResponse response = (HttpServletResponse) resp; 12 response.setHeader("Access-Control-Allow-Origin", "*"); 13 response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 14 response.setHeader("Access-Control-Max-Age", "3600"); 15 response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 16 chain.doFilter(req, resp); 17 } 18 19 public void init(FilterConfig config) throws ServletException { 20 21 } 22 23 }
(2)使用@CrossOrigin註解
1 @RestController 2 @RequestMapping("/account") 3 public class AccountController { 4 5 @CrossOrigin 6 @GetMapping("/{id}") 7 public Account retrieve(@PathVariable Long id) { 8 // ... 9 } 10 11 @DeleteMapping("/{id}") 12 public void remove(@PathVariable Long id) { 13 // ... 14 } 15 }
這是一個很簡單的示例,官方參考文檔還有更加全面的示例。
1 <mvc:cors> 2 3 <mvc:mapping path="/api/**" 4 allowed-origins="http://domain1.com, http://domain2.com" 5 allowed-methods="GET, PUT" 6 allowed-headers="header1, header2, header3" 7 exposed-headers="header1, header2" allow-credentials="false" 8 max-age="123" /> 9 10 <mvc:mapping path="/resources/**" 11 allowed-origins="http://domain1.com" /> 12 13 </mvc:cors>
參考文檔:http://spring.io/blog/2015/06/08/cors-support-in-spring-framework
(3)使用第三方CORSFilter
官網:http://software.dzhuvinov.com/cors-filter.html
3、AJAX發送post請求,數據為json時,data對應的內容應該是json字符串,而不是json字符串
參考資料:
http://start.spring.io/
http://www.jianshu.com/p/d05303d34222
前端-關於CORS跨域的解決方案,面向服務端