本文目錄一覽:
同源策略與跨域問題解決
如果兩個頁面的協議,端口(如果有指定)和域名都相同,則兩個頁面具有相同的 源 。
舉個例子:
下表給出了相對 同源檢測的示例:
由同源策略導致的的AJAX請求失敗
例如:頁面路徑為:
後台接口地址為:
產生的結果:
此即為跨域請求失敗
CORS是一個W3C標準,全稱是”跨域資源共享”(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器,發出 XMLHttpRequest 請求,從而克服了AJAX只能 同源 使用的限制。
在此之前,需要知道 簡單請求、複雜請求
簡單請求:
某些請求不會觸發 CORS 預檢請求 。本文稱這樣的請求為「簡單請求」,請注意,該術語並不屬於 Fetch (其中定義了 CORS)規範。若請求滿足所有下述條件,則該請求可視為「簡單請求」:
複雜請求:
與前述簡單請求不同,「需預檢的請求」要求必須首先使用 OPTIONS 方法發起一個預檢請求到服務器,以獲知服務器是否允許該實際請求。”預檢請求「的使用,可以避免跨域請求對服務器的用戶數據產生未預期的影響。當請求滿足下述任一條件時,即應首先發送預檢請求:
若需要跨域,則需要在請求頭裡添加 Origin 字段
請求至後台若符合後台請求規則則可成功請求,並且後台會返回相應的規則
當請求為複雜請求時,瀏覽器會在請求前先發送一個 OPTIONS 請求
OPTIONS 是一個預檢請求,與簡單請求不同的是它會額外攜帶兩個參數: Access-Control-Request-Method :該次請求的請求方式 Access-Control-Request-Headers :該次請求的自定義請求頭字段
OPTIONS 發送至後台若後台成功響應,則繼續發送複雜請求,若響應失敗則不會發送複雜請求
繼續發送複雜請求
(1)、OPTIONS不會攜帶body若後台方法上使用@RequestBody註解,則會報錯:
例如:
此時需要在@RequestBody後添加參數required=false,允許body為空
即可解決該問題
(2)、OPTIONS請求不應被過多的發送,因為它也是一個http請求也會佔用一部分資源,相應的一種解決方法
在響應中添加緩存字段,以減少OPTIONS請求
(1)、在Java web工程中加如下列過濾器即可
(2)、在nginx中配置
使用反向代理工具解決跨域問題:如 Nginx 、 node.js
以Nginx為例:
在Nginx的配置文件中加入:
啟動Nginx再以
地址訪問頁面
訪問後台接口
發現可正常請求
上述以
地址訪問頁面
訪問後台接口
的方式遵循了,瀏覽器的同源策略自然不存在跨域
Nginx代理了頁面請求和接口請求,所以頁面請求和接口請求都在Nginx源內由Nginx去完成頁面請求和接口的請求即: 內
所以瀏覽器訪問頁面和接口都是以 來進行訪問的,滿足了同源策略自然不存在跨域之說
圖解:
跨域:
Nginx代理,滿足同源策略
Nginx反向代理其實是一種欺騙瀏覽器的方法
[1] 瀏覽器同源政策及其規避方法
[2] XMLHttpRequest Level 2 使用指南
[3] 跨域資源共享 CORS 詳解
[4] HTTP訪問控制(CORS)
Ajax 跨域問題及其解決方案
主流的 前後端分離模式 下,當前端調用後台接口時,由於是在非同一個域下的請求,從而會引發 瀏覽器 的自我安全保護機制,最終結果是 接口成功請求並響應 ,但 前端不能正常處理該返回數據 。
因此,當 同時滿足 以下三個條件的情況下,就會出現跨域問題:
想要徹底解決跨域問題,只需要破壞以上三個條件的任一即可:
添加瀏覽器啟動參數: chrome –disable-web-security ,但是極不推薦這種解決方式。
Jsonp,全稱 JSON with Padding ,一種非官方的協議,而是一種約定;前端通過向後台發送 script 類型請求解決跨域,此時接口響應的 application/javascript 類型的數據會作為 callback 函數的參數進行處理。
所以,後台也需要做相應的處理。以 Java 為例,添加如下配置即可:
綜上, jsonp 請求存在以下幾個弊端:
用 Nginx 或 Apache 來代理調用方的請求( 客戶端變更為相對路徑請求,而非絕對路徑 ),此時對於瀏覽器來說,由於請求是同源的,因此就不存在跨域問題。
以 Java 應用為例,添加如下全局配置:
如果只想針對某個類下的接口,或者是某個具體的接口配置允許跨域,只需要在相應的地方添加註解 @CrossOrigin 即可。
如果配置了 nginx 作為代理服務器,那麼只需要為 nginx 添加支持跨域請求即可:
Q1:瀏覽器在執行跨域請求時,是先執行後判斷,還是先判斷後執行?
A1:都有可能,這需要根據所發送的請求是 簡單請求 還是 非簡單請求 來判斷;如果是非簡單請求,瀏覽器每次在執行真正的請求之前,還會先發送一個 options 請求方式的預檢命令【 可設定緩存時長,取消每次請求都要預檢,提高效率,參考上面的服務端配置 】。關於兩種請求的區分及定義,參考下圖說明:
Q2:如果是允許帶( 被調用方 ) cookie 的跨域請求,此時服務端同樣配置為 Access-Control-Allow-Origin 等於 * ,前端是否還可以請求成功?
A2:不可以,此時要將 Access-Control-Allow-Origin 指定為 調用方 具體的域【 可以先取得調用方的域再動態配置,這樣就不存在多個域請求的限制問題 】,並且添加配置 Access-Control-Allow-Credentials 為 true 。
java跨域怎麼解決
這個問題的回答很多的吧。。
一個是用jsonp的方式
另一種就是在java代碼里接口那裡加上
response.addHeader(“Access-Control-Allow-Origin”, “*”);
response.addHeader(“Access-Control-Allow-Methods”, “GET, POST, PUT, DELETE, OPTIONS”);
response.setHeader(“Access-Control-Allow-Headers”, “x-requested-with”);
java為什麼會有跨域問題
前言
相信大家在寫前端腳本的時候經常會遇到發送數據到後台的情況,但是由於瀏覽器的限制,不同域名之間的數據是不能互相訪問的,那前端怎麼和後端如何進行數據之間的交換呢?
JavaScript由於安全性方面的考慮,不允許頁面跨域調用其他頁面的對象,那麼問題來了,什麼是跨域問題?
答:這是由於瀏覽器同源策略的限制,現在所有支持JavaScript的瀏覽器都使用了這個策略。那麼什麼是同源呢?所謂的同源是指三個方面「相同」:
域名相同
協議相同
端口相同
下面就舉幾個例子來幫助更好的理解同源策略。
URL
說明
是否允許通信
同一域名 允許
不同域名 不允許
同一域名不同端口 不允許
同一域名不同協議 不允許
在JAVA中處理跨域問題,通常有以下兩種常用的解決方法。
第一種解決方法
後台代碼在被請求的Servlet中添加Header設置:
response.setHeader(“Access-Control-Allow-Origin”, “*”);
PrintWriter out =null;
try
{
out = response.getWriter();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print(“{‘status’:’ok’}”);
out.flush();
out.close();
Access-Control-Allow-Origin這個Header在W3C標準里用來檢查該跨域請求是否可以被通過,如果值為*則表明當前頁面可以跨域訪問。默認的情況下是不允許的。
在前端JS中需要向Servlet發出請求,請求代碼如下所示:
$.ajax({
url: “your url”,
type:”get or post”,
dataType:”json”,
data:{
….
},
success:function(data){
…
}
第二種解決方法
通過jsonp跨域請求的方式。JSONP和JSON雖然只有一個字母的區別,但是他們完全就是兩回事,很多人很容易把他們搞混。JSON是一種數據交換的格式,而JSONP則是一種非官方跨域數據交互協議。
首先來說一下前端JS是怎麼發送請求。代碼如下所示:
$.ajax({
url:”your url”,
type:”get or post”,
async:false,
dataType : “jsonp”,
//服務端用於接收callback調用的function名的參數
jsonp:”callbackparam”,
//callback的function名稱
jsonpCallback:”success_jsonpCallback”,
success:function(data){
console.log(data);
},
error:function(data){
console.log(data);
}
});
這裡的callbackparam和success_jsonpCallback可以理解為發送的data數據的鍵值對,可以自定義,但是callbackparam需要和後台約定好參數名稱,因為後台需要獲取到這個參數裏面的值(即success_jsonpCallback)。
下面,最重要的來了,後台怎麼樣獲取和返回數據呢。代碼如下所示:
PrintWriter out =null;
String callback=req.getParameter(“callbackparam”);
String json=callback+”({‘status’:’ok’})”;
try
{
out = resp.getWriter();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print(json);
out.flush();
out.close();
首先需要獲取參數名為callbackparam的值,這裡獲取到的值就是「success_jsonpCallback」。然後將這個值加上一對小括號。小括號里放入你需要返回的數據內容,比如這裡我返回一個JSON對象。當然你也可以返回其他對象,比如只返回一個字符串類型數據也可以。最後前端JS返回的數據就是這樣的:
success_jsonpCallback({‘status’:’ok’})
瀏覽器會自動解析為json對象,這時候你只需要在success回調函數中直接用data.status就可以了。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/283121.html