問題解決 - AJAX跨域問題


No 'Access-Control-Allow-Origin' header is present on the requested resource.

前言

  • ajax跨域問題,主要原因是因為瀏覽器的“同源策略”
  • 若是iframe屬於另外的范疇,可以使用 document.domain
  • 若是改不了后台代碼建議使用nginx,請求都通過nginx轉發

先上解決方案

  1. 將非簡單請求改為簡單請求 注釋掉Content-Type(Content-Type字段的類型為application/json時為非簡單請求。)
  2. 然后在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");

最后

這次總算是摸透了

資料參考

ajax跨域,這應該是最全的解決方案了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM