Spring MVC經過CROS協議解決跨域問題

如今接手學校網絡中心的一個項目,根據團隊成員的實際狀況以及開發須要,老師但願作到先後端徹底分離。後臺使用java提供restful API 做爲核心,前臺不管PC或者移動端能夠共用一個核心。前期解決了哦oauth2,做爲受權機制等問題,本覺得大業將成。(最近打算詳細介紹一下機遇Spring sercurity 實現oauth2的解決方案)結果又出現了一個跨域問題,讓咱們踩了一個大坑,記錄在此,以絕後患。 錯誤信息以下: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403. 什麼是跨域 簡單的說即爲瀏覽器限制訪問A站點下的js代碼對B站點下的url進行ajax請求。好比說,前端域名是www.abc.com,那麼在當前環境中運行的js代碼,出於安全考慮,訪問www.xyz.com域名下的資源,是受到限制的。現代瀏覽器默認都會基於安全緣由而阻止跨域的ajax請求,這是現代瀏覽器中必備的功能,可是每每給開發帶來不便。特別是對我這樣後臺開發人員來說,這個事情簡直神奇。 但跨域的需求卻一直都在,爲了跨域,勤勞勇敢的程序猿們想出了許許多多的方法,例如,jsonP、代理文件等等。但這些作法增長了許多沒必要要的維護成本,並且應用場景也有許多限制,例如jsonP並不是XHR,因此jsonP只能使用GET傳遞參數。更詳細的資料能夠看這裏 Web應用跨域訪問解決方案彙總 CORS協議 現在的JS大有一統天下的趨勢,瀏覽器已經成了大多應用最好的安身之所。哪怕在移動端也有各類Hybird方案,在本地文件系統的Web頁面,也有須要獲取外部數據的需求,而這些需求也必然是跨域的。在尋找跨域解決方案時,發現了最優雅解決方案就是HTML5來帶了的「Cross-Origin Resource Sharing」的新特性,來賦予開發者權力決定資源是否容許被跨域訪問。 CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。 它容許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。 爲何說它優雅呢? 整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。 所以,實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨源通訊。 解決這個問題的關鍵就落在了我這個負責後臺的程序猿身上。 看看文檔也不是什麼難事嘛,就是須要在http頭中設置Access-Control-Allow-Origin來決定須要容許哪些站點來訪問。關於CROS協議更詳細內容參考跨域資源共享 CORS 詳解 CROS常見header CORS具備如下常見的header Access-Control-Allow-Origin: http://kbiao.me Access-Control-Max-Age: 3628800 Access-Control-Allow-Methods: GET,PUT, DELETE Access-Control-Allow-Headers: content-type "Access-Control-Allow-Origin"代表它容許" http://kbiao.me "發起跨域請求 "Access-Control-Max-Age"代表在3628800秒內,不須要再發送預檢驗請求,能夠緩存該結果(上面的資料上咱們知道CROS協議中,一個AJAX請求被分紅了第一步的OPTION預檢測請求和正式請求) "Access-Control-Allow-Methods"代表它容許GET、PUT、DELETE的外域請求 "Access-Control-Allow-Headers"代表它容許跨域請求包含content-type頭 固然在處理這個問題的時候前端也有很多坑,特別是Chrome瀏覽器不容許localhost的跨域請求,詳細方案見我項目中負責前端解決方案的小夥伴。僞裝有連接 常規解決方案 知道了問題的緣由,也知道了配套的解決辦法,如今就讓咱們來實現解決。思路很簡單,當前端要請求跨域資源時候,咱們給它加上響應的響應頭便可。很顯然咱們本身定義一個過濾器是最簡單不過了。 /** * Created by kangb on 2016/5/10. */ @Component public class myCORSFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) servletResponse; String origin = (String) servletRequest.getRemoteHost()+":"+servletRequest.getRemotePort(); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization"); response.setHeader("Access-Control-Allow-Credentials","true"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } } @Component 是Spring的註解,關鍵部分在doFilter中,添加了咱們須要的頭,option是預檢測須要因此須要容許,Authorization是作了oauth2登陸響應所必須的,Access-Control-Allow-Credentials表示容許cookies。都是根據本身項目的實際須要配置。 再配置Web.xml使得過濾器生效 cors ·CLASS_PATH·.myeCORSFilter cors /api/* 接下來前端就能夠像往常同樣使用AJAX請求得到資源了,徹底不須要作出什麼改變。 SPRING 4中更優雅的辦法 SpringMVC4提供了很是方便的實現跨域的方法。在requestMapping中使用註解。 @CrossOrigin(origins = 「http://kbiao.me」) 全局實現 .定義類繼承WebMvcConfigurerAdapter,設置跨域相關的配置 public class CorsConfigurerAdapter extends WebMvcConfigurerAdapter{ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/*").allowedOrigins("*"); } } 將該類注入到容器中: 更詳細的內容參考Spring 官方的hello world案例Enabling Cross Origin Requests for a RESTful Web Service http://spring.io/guides/gs/rest-service-cors/或者使用git下載示例源碼 https://github.com/spring-guides/gs-rest-service-cors.git
 前端

相關文章
相關標籤/搜索