跨域請求的常用方式及解釋

来源:https://www.cnblogs.com/chaixiaozhi/archive/2018/03/12/8545462.html
-Advertisement-
Play Games

同源策略 首先基於安全的原因,瀏覽器是存在同源策略這個機制的,同源策略阻止從一個域載入的腳本去獲取另一個域上的文檔屬性。也就是說,受到請求的 URL 的域必須與當前 Web 頁面的域相同。這意味著瀏覽器隔離來自不同源的內容,以防止它們之間的操作。 js跨域是指通過js在不同的域之間進行數據傳輸或通信 ...


同源策略

首先基於安全的原因,瀏覽器是存在同源策略這個機制的,同源策略阻止從一個域載入的腳本去獲取另一個域上的文檔屬性。也就是說,受到請求的 URL 的域必須與當前 Web 頁面的域相同。這意味著瀏覽器隔離來自不同源的內容,以防止它們之間的操作。

js跨域是指通過js在不同的域之間進行數據傳輸或通信,比如用ajax向一個不同的域請求數據,或者通過js獲取頁面中不同域的框架中(iframe)的數據。

只要協議、功能變數名稱、埠有任何一個不同,都被當作是不同的域。

 

下麵介紹幾種常用的跨域請求方式

預設埠為:8080

一、利用jQuery獲取jsonp

JSONP的原理與實現思路

1)Web頁面調用js文件,可跨域。擴展:但凡有src屬性的標簽都具有跨域能力。
2)跨域伺服器 動態生成數據 並存入js文件(通常json尾碼),供客戶端調用。
3)為了便於客戶端使用數據,形成一個非正式傳輸協議,稱為JSONP。該協議重點是允許用戶傳遞一個callback參數給伺服器,然後伺服器返回數據時 將此callback參數作為函數名包裹住JSON數據,使得客戶端可以隨意定製自己的函數來自動處理返回數據。

 

 1.1如果我們不用跨域請求的寫法的話:

$('#cors1').click(function () {
    $.ajax({
        type:'get',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});

1.2使用跨越請求的寫法,最簡單的就是設置dataType:jsonp:

jsonp指定伺服器返回的數據類型為jsonp格式,可以看發起的請求路徑,自動帶了一個callback=xxx,xxx是jquery隨機生成的一個回調函數名稱。

這裡的success預設success()作為回調函數。數據返回到前端後,就是success(result)的形式,因為是script腳本,所以自動調用success函數,而result就是success的參數。

$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});
    @RequestMapping(value="/say", method = RequestMethod.GET)      //後端代碼
    public String say(@RequestParam("callback") String callback){

        //callback前端傳過來的回調函數名稱

        //數據
        String result = "{age:22}";
        
        //用回調函數名稱包裹返回數據,這樣,返回數據就作為回調函數的參數傳回去了
        result = callback + "(" + result + ")";
        return result;
        
    }

 

1.3jsonpCallback

為jsonp請求指定一個回調函數名。這個值將用來取代jQuery自動生成的隨機函數名。

調用回調函數的時候,先調用了指定的showData,然後再調用了success。

$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',   //指定伺服器返回的數據類型 
        jsonpCallback: 'showData',    //指定回調函數名稱
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});

function showData(data) {
    console.log("show"+data);
}

1.4jsonp

在一個jsonp請求中重寫回調函數的名字。這個值用來替代在"callback=?"這種GET或POST請求中URL參數里的"callback"部分,比如{jsonp:'onJsonPLoad'}會導致將"onJsonPLoad=?"傳給伺服器。

$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',
        jsonpCallback: 'showData',
        jsonp: 'sendParam',  //指定參數名稱
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});

function showData(data) {
    console.log(data);
}

指定jsonp後,後端也要改變:

    @RequestMapping(value="/say", method = RequestMethod.GET)
    public String say(@RequestParam("sendParam") String sendParam){

        //sendParam前端傳過來的回調函數名稱

        //數據
        String result = "{age:22}";

        //用回調函數名稱包裹返回數據,這樣,返回數據就作為回調函數的參數傳回去了
        result = sendParam + "(" + result + ")";
        return result;

    }

 

 

1.5jsonp方式不支持POST方式跨域請求,就算指定成POST方式,會自動轉為GET方式;而後端如果設置成POST方式了,那就請求不了了。

 

二、設置CORS頭“Access-Control-Allow-Origin”

  •  CORS的原理:
     CORS定義一種跨域訪問的機制,可以讓AJAX實現跨域訪問。CORS 允許一個域上的網路應用向另一個域提交跨域 AJAX 請求。實現此功能非常簡單,只需由伺服器發送一個響應標頭即可。  
$('#cors1').click(function () {
    $.ajax({
        type:'get',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});
    @RequestMapping(value="/say", method = RequestMethod.GET)
    public String say(HttpServletRequest request, HttpServletResponse response){
        //設置響應頭
        response.setHeader("Access-Control-Allow-Origin","*");  //當前我設置的header為“*”,任意一個請求過來之後服務端我們都可以進行處理&響應
    // 指定特定功能變數名稱可以訪問
       response.setHeader("Access-Control-Allow-Origin", "http:localhost:8080/")
//數據
        String result = "{age:22}";
        return result;
    }

 

 

三、iframe+window.postMessage實現跨域

script、image、iframe的src都不受同源策略的影響。所以我們可以藉助這一特點,實現跨域。

postMessage()方法允許來自不同源的腳本採用非同步方式進行有限的通信,可以實現跨文本檔、多視窗、跨域消息傳遞。

 

發送消息

postMessage(data,origin)方法接受兩個參數

 1.data:要傳遞的數據,html5規範中提到該參數可以是JavaScript的任意基本類型或可複製的對象,然而並不是所有瀏覽器都做到了這點兒,部分瀏覽器只能處理字元串參數,所以我們在傳遞參數的時候需要使用JSON.stringify()方法對對象參數序列化,在低版本IE中引用json2.js可以實現類似效果。

2.origin:字元串參數,指明目標視窗的源,協議+主機+埠號[+URL],URL會被忽略,所以可以不寫,這個參數是為了安全考慮,postMessage()方法只會將message傳遞給指定視窗,當然如果願意也可以建參數設置為"*",這樣可以傳遞給任意視窗,如果要指定和當前視窗同源的話設置為"/"。

<iframe id="ifr" src="http://localhost:8081/girl/b.html"></iframe>
window.onload = function () {
    var ifr = document.getElementById("ifr");
    ifr.contentWindow.postMessage("crsf","http://localhost:8081");
};

接收消息

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>testb</title>
</head>
<body>
    <div>b</div>
</body>
</html>
<script>
window.addEventListener('message', function(event){
console.log('origin: '+event.origin);    //origin: http://localhost:8080
console.log('data: '+event.data);      //data: crsf
console.log(event.source);
// 回發數據
event.source.postMessage('hello world', event.origin);
});
</script>

有幾個重要屬性

  1. origin:發送消息視窗的源(協議+主機+埠號)
  2. data:顧名思義,是傳遞來的message
  3. source:發送消息的視窗對象

這樣就可以接收跨域的消息了,我們還可以發送消息回去。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 異常: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object 這是在intent發送數據的時候出現的,原因:通過intent傳遞的類實現了serialzable介面,但是那 ...
  • 恢復內容開始 打開monitor時出現 打開log一看,媽的,全是報錯日誌 真是聞者傷心,見者落淚。 隨便摘錄一篇日誌: 那麼長???!!!沒法看了,直接上網搜索。 第一種方法:據說是從外網stackoverflow流傳過來的秘方:只要用管理員身份打開就可以解決了。 實踐之後:完全不頂用啊!!! 第 ...
  • 最近在項目中需要做自動定位功能,就是你在參加會議通過掃描二維碼簽到的時候自動定位並將你的定位信息在簽到中上傳,這樣可以避免我們進行假簽到。在這個功能中,主要用到的是系統自帶的定位模塊,首先我們是需要配置定位功能的參數,然後當我們定位成功時調用特定的方法進行相應操作就可以了,當然,在定位失敗時我們也可 ...
  • 使用的自定義類,如下: 動態變數控制 動態添加方法 動態交換兩個方法的實現 攔截並替換方法 在方法上增加額外功能 對runtime進行歸納總結,代碼如下: 1、載入運行時頭文件: 2、具體實現代碼: ...
  • 簡要:本系列文章講會對expo進行全面的介紹,本人從2017年6月份接觸expo以來,對expo的研究斷斷續續,一路走來將近10個月,廢話不多說,接下來你看到內容,講全部來與官網 我猜去全部機翻+個人修改補充+demo測試的形式,對expo進行一次大補血!歡迎加入expo興趣學習交流群:597732 ...
  • 簡要:本系列文章講會對expo進行全面的介紹,本人從2017年6月份接觸expo以來,對expo的研究斷斷續續,一路走來將近10個月,廢話不多說,接下來你看到內容,講全部來與官網 我猜去全部機翻+個人修改補充+demo測試的形式,對expo進行一次大補血!歡迎加入expo興趣學習交流群:597732 ...
  • 簡要:本系列文章講會對expo進行全面的介紹,本人從2017年6月份接觸expo以來,對expo的研究斷斷續續,一路走來將近10個月,廢話不多說,接下來你看到內容,將全部來與官網 我猜去全部機翻+個人修改補充+demo測試的形式,對expo進行一次大補血!歡迎加入expo興趣學習交流群:597732 ...
  • 通過閱讀本文,你會對熱修複技術有更深的認知,本文會列出各類框架的優缺點以及技術原理,文章末尾簡單描述一下Tinker的框架結構。本文框架: 1. 什麼是熱修複? 2. 熱修複框架分類 3. 技術原理及特點 4. Tinker框架解析 5. 各框架對比圖。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...