標籤:
什麼是跨域請求問題?
這個問題的起因在於現代瀏覽器預設都會基於安全原因而阻止跨域的ajax請求,這是現代瀏覽器中必備的功能,但是往往給開發帶來不便。
但跨域的需求卻一直都在,為了跨域,勤勞勇敢的程式猿們想出了許許多多的方法,例如,jsonP、代理檔案等等。但這些做法增加了許多不必要的維護成本,而且應用情境也有許多限制,例如jsonP並非XHR,所以jsonP只能使用GET傳遞參數。
在行動裝置 App風生水起的如今,托HTML5的福,Mobile Web,甚至Hybird App也逐漸火起來,在本地檔案系統的Web頁面,也有需要擷取外部資料的需求,而這些需求也必然是跨域的。同時,HTML5也來帶了叫“Cross-Origin Resource Sharing”的新特性,來賦予開發人員權力決定資源是否允許被跨域訪問。
如何解決?
CORS,CrossOrigin Resources Sharing,也即跨源資源共用,是 HTML5 的一項特性,它定義了一種瀏覽器和伺服器互動的方式來確定是否允許跨域請求。
通過伺服器增加一個特殊的Header[Access-Control-Allow-Origin]來告知用戶端跨域的限制,如果瀏覽器支援CORS的話,如果判斷Origin通過的話,就會允許XHR進行請求,而不需要再使用jsonP或者代理檔案。
使用這個Header返回被允許請求跨域請求的來源域,例如網站duelist.cn設定了下面的Header
Access-Control-Allow-Origin: http://smdcn.net
這樣設定之後,通過http://smdcn.net下的頁面對於duelist.cn進行ajax請求就會被允許,而其他網站對duelist.cn依舊會被阻攔,通過這種方式網站擁有者可以自己對此進行限制。
當然,如果不想限制來源,可以通過
Access-Control-Allow-Origin: *
來允許任何網站對該資源進行跨域請求
在SpringMVC下的解決方案:
定義SimpleCORSFilter
import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Component;@Componentpublic class SimpleCORSFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; 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"); chain.doFilter(req, res); } public void init(FilterConfig filterConfig) {} public void destroy() {}}
web.xml:
<filter> <filter-name>cors</filter-name> <filter-class>com.app.filter.SimpleCORSFilter</filter-class> </filter> <filter-mapping> <filter-name>cors</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
angularjs端代碼:
$http({ method: "post", url: "http://localhost:8080/eifs/usr/login.json", data: {para1:"para1",para2:"para2"}, headers: { ‘Content-Type‘: ‘application/x-www-form-urlencoded‘ } }).success(function (data) { }).error(function (data) { }); $http.get(‘http://localhost:8080/eifs/usr/login.json‘, {params:{para1:"para1",para2:"para2"},timeout: 10000}) .success(function (data, status, headers, config) { }).error(function (data, status, headers, config) { });
參考:
spring guide:https://spring.io/guides/gs/rest-service-cors/
SpringMvc+AngularJS通過CORS實現跨域方案