1. 程式人生 > >java利用cors實現跨域請求

java利用cors實現跨域請求

什麼是跨域?

跨域,指的是瀏覽器不能執行其他網站的指令碼。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript施加的安全限制。

ajax本身實際上是通過XMLHttpRequest物件來進行資料的互動,而瀏覽器出於安全考慮,不允許js程式碼進行跨域操作,所以會警告。

常見解決跨域的方式

  • script標籤
  • iframe
  • jsonp
  • 服務端中轉請求
  • cors

cors

全稱:Cross-Origin Resource Sharing

中文意思:跨域資源共享

它在維基百科上的定義是:跨域資源共享(CORS )是一種網路瀏覽器的技術規範,它為Web伺服器定義了一種方式,允許網頁從不同的域訪問其資源。而這種訪問是被同源策略所禁止的。CORS系統定義了一種瀏覽器和伺服器互動的方式來確定是否允許跨域請求。 它是一個妥協,有更大的靈活性,但比起簡單地允許所有這些的要求來說更加安全。

什麼是跨域請求問題?

這個問題的起因在於現代瀏覽器預設都會基於安全原因而阻止跨域的ajax請求,這是現代瀏覽器中必備的功能,但是往往給開發帶來不便。

但跨域的需求卻一直都在,為了跨域,勤勞勇敢的程式猿們想出了許許多多的方法,例如,jsonP、代理檔案等等。但這些做法增加了許多不必要的維護成本,而且應用場景也有許多限制,例如jsonP並非XHR,所以jsonP只能使用GET傳遞引數。

在移動應用風生水起的如今,託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;
@Component
public 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-Origin", request.getHeader("Origin"));//cookie共享用這個配置
   response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token"); 
        response.setHeader("Access-Control-Allow-Credentials", "true");//cookie 共享
        response.setHeader("XDomainRequestAllowed","1"); 
    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) {
});
//cookie 共享時 配置 withCredentials :true
$http.get("http://127.0.0.1:8080/xxx/syslogin/login?account=%E5%B0%8F%E7%81%B0&password=123456",{withCredentials: true});