標籤:服務 回應標頭 form int 網站 mvc jquery style header
在我們開發當中 經常會碰見跨域問題 今天我來說下 我在工作撞見的跨域;
一.首先我們要瞭解跨域存在的原因
1、瀏覽器限制
2、跨域(網域名稱,連接埠不一樣都是跨域)
3、XHR(XMLHttpRequest請求)
解決方案
- 【策略一】Jsonp 需要目標伺服器配合一個callback函數
從XHR(XMLHttpRequest)出發
避免發生跨域。使用jsonp,由於jsonp請求是通過script的方式發送的(只有xhr的請求方式才有可能產生跨域問題),所以不會產生跨域問題。Spring MVC實現過程:前台使用ajax的get請求,將dataType設為“jsonp”;伺服器建立一個類並繼承抽象類別AbstractJsonReponseBodyAdvice,最後註解@ControllerAdivece。使用jsonp的弊端,只能使用get方式請求,伺服器需要改動代碼,發送的不是xhr請求。
使用該方式的缺點:請求方式只能是get請求
方式二:使用jQuery的jsonp外掛程式
外掛程式下載網址:https://github.com/jaubourg/jquery-jsonp
前端代碼
伺服器代碼
使用該方式的特點:與方式一相比,請求方式不只局限於get請求,還可以是post請求,但從伺服器從擷取的資料依然是jsonp格式
- 【策略二】修改服務端代碼 支援跨域
產生跨域後解決。
從被呼叫者考慮,有三種情況,分別是伺服器實現,nginx配置和apache配置。
伺服器實現需要注意兩種情況,簡單請求和非簡單請求。簡單請求是先執行請求再驗證,非簡單請求是先驗證再請求。
簡單請求(比較常見):方法為get,head,post,請求header裡面沒有自訂頭,Content-Type的值為以下幾種 text/plain,multipart/form-data,application/x-www-form-urlencoded。
非簡單請求(比較常見):put,delect方法的ajax請求,發送json格式的ajax請求,帶自訂頭的ajax請求。
簡單請求處理方案:在回應標頭中添加
Access-Control-Allow-Origin=“允許跨域的url”,即跨省域時,要求標頭Origin的值,所以一般是擷取Origin的值。
Access-Control-Allow-Method=“*”,允許的方法。
非簡單請求處理方案:在相應頭中添加
Access-Control-Allow-Origin=“允許跨域的url”,即跨域時,可以擷取要求標頭Origin的值。
Access-Control-Allow-Method=“*”,允許的方法
Access-Control-Request-Headers=“Content-Type,自訂的header的key”。
帶cookies的跨域解決:在回應標頭添加
Access-Control-Allow-Credentials,="true",允許使用cookies
伺服器代碼
使用該方式的特點:與前兩種方式相比,前端代碼和未處理跨域前一樣,即普通的ajax請求,但伺服器代碼添加了一段解決跨域的代碼
// 設定:Access-Control-Allow-Origin頭,處理Session問題
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("P3P", "CP=CAO PSA OUR");
if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
response.addHeader("Access-Control-Allow-Methods", "POST,GET,TRACE,OPTIONS");
response.addHeader("Access-Control-Allow-Headers", "Content-Type,Origin,Accept");
response.addHeader("Access-Control-Max-Age", "120");
}
cors進階使用:在springmvc中配置攔截器
建立跨域攔截器實現HandlerInterceptor介面,並實現其方法,在請求處理前設定頭資訊,並允許存取
在springmvc的設定檔中配置攔截器,注意攔截的是所有的檔案
- 被調方的nginx 處理
ngnix配置:
apache配置:沒搞過
若是使用spring架構:使用@CrossOrigin註解既可以實現服務端跨域
- 調用方的nginx處理
- 修改網站的nginx設定檔並重啟nginx
server { listen 80; server_name www.a.com; access_log logs/test.access.log; # 匹配以/apis/開頭的請求 location ^~ /apis/ { proxy_pass http://www.b.com/; #注意網域名稱後有一個/ } location / { root html/a; index index.html index.htm; } # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
沒錯就是proxy_pass後面的地址加一個/
java跨域