關於跨域請求

来源:http://www.cnblogs.com/yinxingen/archive/2017/12/08/8007335.html
-Advertisement-
Play Games

跨域問題的產生: 因為瀏覽器有同源策略,只有在同功能變數名稱,同埠,同協議的情況下才可以進行數據交互;有的時候,例如:在公司開發項目的時候,前端開發的伺服器可能和後端伺服器不是同一個,因為可能是通過gulp、webpack搭建的開發伺服器,就需要解決跨域問題,再例如,在大公司數據伺服器不只有一個,所以跨域 ...


跨域問題的產生:

因為瀏覽器有同源策略,只有在同功能變數名稱,同埠,同協議的情況下才可以進行數據交互;有的時候,例如:在公司開發項目的時候,前端開發的伺服器可能和後端伺服器不是同一個,因為可能是通過gulp、webpack搭建的開發伺服器,就需要解決跨域問題,再例如,在大公司數據伺服器不只有一個,所以跨域問題也必然存在

一、jsonp解決跨域請求

jsonp是一種前後端結合的跨域方式,原理就是通過script標簽的src屬性來進行數據請求,src不受同源策略的影響,故而能請求到數據,需要註意的是,數據處理需要通過回調函數來進行,而本質上,我們把回調函數的名字告訴後端,後端將數據放入到回調函數里,所以說需要告知後端,回調函數是什麼,這也就是為什麼說jsonp是前後端結合的方式。

註意:一個script只能請求一次,多次請求應該去動態的創建script,回調函數也只能使用一次,所以也需要動態創建 ,使用完成後移除,避免污染全局空間

缺點:jsonp只能get請求

1、nodejs代碼,配置路由(使用express模塊)

//後端的任務,就是把數據放到前端的那個函數里並給它執行一下
//直接返回這個操作的js字元串,因為這個字元串會被script當成js代碼來運行
app.get('/data', function(req, res) {
    //前端回調函數的名字         
    let fn = req.query['callback'];
    //註意,在content 後拼接一個空字元串,將獲取的數據轉義正常輸出,否則有時候讀取的數據格式為buffer數據類型    
    var content = fs.readFileSync('./datas/data.json') + ''; 
    //返回給前端函數數據            
    res.send(fn + '(' + content + ')');
});
2、js代碼,返回數據(函數中用到的是es6解構賦值參數)
Jsonp({         
    url: "http://localhost:3000/data",
    success(results) { 
        console.log(results)
    }
})

function Jsonp({ url, success }) {
    //動態創建script標簽         
    let $script = $("")
        //隨機函數名字         
    var random_name = 'random_fn_' + Date.now()
        //創建的隨機全局函數
    window[random_name] = function(data) {
        success(data)
            //處理完數據之後,將script刪掉,函數delete掉
        $script.remove()
        delete window[random_name] 
    }     
    $script[0].src = url + '?callback=' + random_name 
    $("body").append($script)

}

二、cors解決跨域請求

cors純後端的解決方式,每次請求都會有一個origin信息被後端捕捉,後端可以通過設置對這個origin的域允許訪問來解決跨域問題

1、nodejs代碼

app.get("/data_cors", (req, res) => {
    //此次請求的源信息
    var reqOrigin = req.header("origin");
    //如果源信息存在,且源是運行訪問的
    if (reqOrigin != undefined && reqOrigin.indexOf("http://localhost:9000") > -1) {
        //設置允許 http://localhost:3000 這個域響應                 
        res.header("Access-Control-Allow-Origin", "http://localhost:9000");
        //允許這個域訪問            
        res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
        //允許的請求方法            
        res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");       
    }       
    res.send('123')

})
2、js代碼獲取返回的數據

$.ajax({
      url:"http://localhost:3000/data_cors",
      success(results){
          console.log(results)
      }
})

三、服務端代理proxy解決跨域請求

因為伺服器間的數據交互沒有跨域限制,所以我們可以通過一個中間代理伺服器來請求目標伺服器的數據,也就是開發伺服器發送請求到代理伺服器,代理伺服器再請求目標伺服器,將數據返回給開發伺服器

1、nodejs代碼

//目標伺服器介面 3000:
app.get("/data_proxy",(req,res)=>{
          //此次請求的源信息
          res.send('proxy')
})
2、代理伺服器1234app.get("/to3000", (req, res) => {
    //代理伺服器1234對9000做跨域處理        
    var reqOrigin = req.header("origin");
    //如果源信息存在,且源是運行訪問的        
    if (reqOrigin != undefined && reqOrigin.indexOf("http://localhost:9000") > -1) {
        //設置允許 http://localhost:3000 這個域響應            
        res.header("Access-Control-Allow-Origin", "http://localhost:9000");
        //允許這個域訪問          
        res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
        //允許的請求方法             
        res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
    }     
    //獲取到9000真正要調用的3000目標伺服器的介面
           
    var url = req.query['url']
    let _res = res
        //代理伺服器1234像目標伺服器3000發送請求(沒有跨域限制)
    http.get(url, (res) => {
        let result = ''
        res.on("data", (chunk) => {              
            result += chunk      
        })
        res.on("end", () => {
            console.log(result)
                //代理伺服器1234將請求到的目標伺服器3000的數據返回給開發伺服器9000
            _res.send(result) 
        })     
    })
})
app.listen(1234);

3、js代碼,開發伺服器9000//當前伺服器9000向代理伺服器1234發送請求
$.ajax({   
    url: "http://localhost:1234/to3000",
    data: {    
        url: "http://localhost:3000/data_proxy"   
    },
       success(results) {      
        console.log(results)   
    }
})

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

-Advertisement-
Play Games
更多相關文章
  • web服務 處於應用層的http協議負責的數據傳輸與解析。位於socket上層,用socket傳輸http數據時需要在消息開頭處聲明是http協議/相應http版本 狀態碼 狀態碼含義 \r\n\r\n 真正的字元串內容。 HTML是什麼 Hypertext Markup Language,是一種標 ...
  • 前言 網路早期最大的問題之一是如何管理狀態。簡而言之,伺服器無法知道兩個請求是否來自同一個瀏覽器。當時最簡單的方法是在請求時,在頁面中插入一些參數,併在下一個請求中傳回參數。這需要使用包含參數的隱藏的表單,或者作為URL參數的一部分傳遞。這兩個解決方案都手動操作,容易出錯。 網景公司當時一名員工Lo ...
  • 註:本文轉載自大神同學的博客,http://www.cnblogs.com/st-leslie/p/5617130.html ,僅供學習不用於其他用途,大家想要更多的乾貨,請移步到該大神博客園 一、什麼是localStorage、sessionStorage 在HTML5中,新加入了一個localS ...
  • 一、介紹 本次博客主要介紹函數表達式的內容,主要是閉包。 二、函數表達式 定義函數的兩種方式:一個是函數聲明,另一個就是函數表達式。 區別: 1.函數聲明是用function後面有函數名,函數表達式是賦值形式給一個變數。 2.函數聲明可以提升函數,而函數表達式不會提升 函數提升就是函數會被自動提升到 ...
  • //多個值同時變化function getStyle(obj, name)//函數幫助獲取不在行間樣式,不受非行間border,padding等得影響{ //style只獲取行間樣式。offset受非行間border,padding等得影響 if(obj.currentStyle) { return ...
  • 1.JS事件的基本知識 JS事件的學習和JS方法的學習揉雜在一起,JS相對於Java等語言,方法定義和使用上比較隨意和簡單,但是還是有一些區別,需要理清楚. 2.jQuery方式綁定事件 這裡多多贅述一點,由於jQuery可以理解為是對JS的一種高級封裝,這種封裝是單向的,所以我們可以在JS中加入j ...
  • 地圖與地理定位 定位在大部分項目中都需要實現,如何實現主要有如下的幾種方法 1. H5定位 在HTML5中navigator有很強大的功能,其中就有定位的方法 這個服務其實是谷歌提供的,在我們國內使用的可能性較低 2. 後端定位 前端調用一個後端提供的介面,後端進行定位操作,返回給前端 在工作中公司 ...
  • 基礎數據結構與演算法 現在有兩個不同的JSON,比較複雜,可以參考這裡的DEMO中返回的JSON。要比較它們的差異,除了用現成的工具如beyond compare以外,如果我們的機器上沒有安裝這個工具,能如何較快解決?作為一個程式員,一個個對比是不可行的,對比完也不會有什麼收穫。我會把之放進Excel ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...