No 'Access-Control-Allow-Origin' header is present on the requested resource.
前言
- ajax跨域問題,主要原因是因為瀏覽器的“同源策略”
- 若是iframe屬於另外的范疇,可以使用 document.domain
- 若是改不了后台代碼建議使用nginx,請求都通過nginx轉發

先上解決方案
- 將非簡單請求改為簡單請求 注釋掉Content-Type(Content-Type字段的類型為application/json時為非簡單請求。)
- 然后在Servlet中的response 添加頭信息 Access-Control-Allow-Origin
- 如:
response.setHeader("Access-Control-Allow-Origin", "*");
修改前狀態 - 現象如下



修改完成后 - 現象如下

跨域的簡要描述
在A網站中,我們希望使用Ajax來獲得B網站中的特定內容。如果A網站與B網站不在同一個域中,那么就出現了跨域訪問問題。你可以理解為兩個域名之間不能跨過域名來發送請求或者請求數據,否則就是不安全的。跨域訪問違反了同源策略,
同源策略規定,瀏覽器的ajax只能訪問跟它的HTML頁面同源(相同域名或IP)的資源。
補充:127.0.0.1 訪問 本地的IP也算跨域 (可方便測試)
- 現在所有支持JavaScript的瀏覽器都會使用這個策略
- 協議、域名、端口號都相同,只要有一個不相同,那么都是非同源。
- 同源策略限制的情況:
- Cookie、LocalStorage 和 IndexDB 無法讀取
- DOM 和 Js對象無法獲得
- AJAX 請求不能發送
- 注意:對於像 img、iframe、script 等標簽的src屬性是特例,它們是可以訪問非同源網站的資源的。
CORS實現原理
CORS是一個W3C標准,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
基本上目前所有的瀏覽器都實現了CORS標准,其實目前幾乎所有的瀏覽器ajax請求都是基於CORS機制的,只不過可能平時前端開發人員並不關心而已(所以說其實現在CORS解決方案主要是考慮后台該如何實現的問題)。
只要同時滿足以下兩大條件,就屬於簡單請求。
(1) 請求方法是以下三種方法之一:
- HEAD
- GET
- POST
(2)HTTP的頭信息不超出以下幾種字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
Java解決方案
無論是使用webservice還是servlet請求都需要通過doPost或者doOptions方法
若是你是HTTP請求
@Override
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
resp.setHeader("Access-Control-Allow-Credentials", "true");
if (req.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(req.getMethod())) {
resp.addHeader("Access-Control-Allow-Methods", "POST,GET,TRACE,OPTIONS,DELETE");
resp.addHeader("Access-Control-Allow-Headers", "Content-Type,Origin,Accept");
resp.addHeader("Access-Control-Max-Age", "1800");
}
super.doOptions(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
resp.setHeader("Access-Control-Allow-Credentials", "true");
if (req.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(req.getMethod())) {
resp.addHeader("Access-Control-Allow-Methods", "POST,GET,TRACE,OPTIONS,DELETE");
resp.addHeader("Access-Control-Allow-Headers", "Content-Type,Origin,Accept");
resp.addHeader("Access-Control-Max-Age", "1800");
}
// ....
}
若是是webservice請求,我這里使用的是Axis2,只需要在頭中多加一個SOAPAction
Servlet需要使用自己的直接繼承AxisServlet,然后重寫doPost和doOptions
resp.addHeader("Access-Control-Allow-Headers", "Content-Type,Origin,Accept,SOAPAction");
最后
這次總算是摸透了
