国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

那些年曾談起的跨域

galois / 2717人閱讀

摘要:在中,在不同的域名下面進行數(shù)據(jù)交互,就會遇到跨域問題,說到跨域首先要從同源說起,瀏覽器為了提供一種安全的運行環(huán)境,各個瀏覽器廠商協(xié)定使用同源策略。在上面說過是不受同源策略限制的,但是出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源請求。

對于前端開發(fā)來說跨域應該是最不陌生的問題了,無論是開發(fā)過程中還是在面試過程中都是一個經(jīng)常遇到的一個問題,在開發(fā)過程中遇到這個問題的話一般都是找后端同學去解決,以至于很多人都忽略了對跨域的認識。為什么會導致跨域?遇到跨域又怎么去解決呢?本文會對這些問題一一的介紹。

JavaScript中,在不同的域名下面進行數(shù)據(jù)交互,就會遇到跨域問題,說到跨域首先要從同源說起,瀏覽器為了提供一種安全的運行環(huán)境,各個瀏覽器廠商協(xié)定使用同源策略。

什么同源策略

同源策略:同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。可以說Web是構(gòu)建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現(xiàn)。

同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSSCSRF等攻擊。所謂同源是指協(xié)議+域名+端口三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。

Url組成部分

了解同源策略以后,同樣需要對url的組成部分也順帶了解一下吧,只有了解url之后當出現(xiàn)跨域的時候才知道哪里出了問題,這樣才能和后端、運維開懟,懟天懟地對空氣。O(∩_∩)O哈哈~其實不是啦,當然是為了能夠和其他同事能做到良好的溝通,說的的有理有據(jù),以理服人嘛,這才是王道。

從上圖中能夠清晰的看出url中每個部分的含義:

protocol:協(xié)議常用的協(xié)議是http

auth:驗證,因為明文傳輸用戶名和密碼,非HTTPS環(huán)境下很不安全,一般用的非常少。

hostname:主機地址,可以是域名,也可以是IP地址

port:端口http協(xié)議默認端口是:80端口,如果不寫默認就是:80端口

pathname:路徑網(wǎng)絡資源在服務器中的指定路徑

serarch:查詢字符串如果需要從服務器那里查詢內(nèi)容,在這里編輯

hash:哈希網(wǎng)頁中可能會分為不同的片段,如果想訪問網(wǎng)頁后直接到達指定位置,可以在這部分設置

項目過程過程中經(jīng)常會用到一些緩存,瀏覽器為了網(wǎng)頁的安全在緩存的時候,由于同源策略的問題對其緩存內(nèi)容進行了限制,其實想想也是對的,如果不使用同源策略的話,很容易沖掉緩存的東西。

CookieLocalStorageIndexDB等無法讀取。

DOM無法獲得。

AJAX請求不能發(fā)送。

當然瀏覽器也沒有把所有的東西都限制了,比如圖片、互聯(lián)網(wǎng)資源等還是允許跨域請求的。允許跨域請求都是使用標簽,只有三個標簽是允許跨域加載資源:

http://localhost:7000/b.html










http://localhost:6000/c.html










a.html中有一個隱藏的iframe,該iframe指向異域http://localhost:7000/b.htmlb.html,且傳遞hash值給b.html`b.html獲取hash值,生成data值,然后動態(tài)創(chuàng)建iframe,該iframedata值傳給與a.html同域的c.html 因為c.htmla.html`同域,可以傳值固然也就解決了跨域問題。

window.name

window.name這個屬性不是一個簡單的全局屬性只要在一個window下,無論url怎么變化,只要設置好了window.name,那么后續(xù)就一直都不會改變,同理,在iframe中,即使url在變化,iframe中的window.name也是一個固定的值,利用這個,我們就可以實現(xiàn)跨域了。

http://localhost:6000/a.html


http://localhost:7000/b.html

var person = {
  name: "Aaron",
  age: 18
}
window.name = JSON.stringify(person)

http://localhost:6000/proxy.html





proxy


這是proxy頁面

http://localhost:6000下有一個a.html,在http://localhost:7000下有一個b.html,在http://localhost:6000/a.html中創(chuàng)建了一個iframe標簽并把地址指向了http://localhost:7000/b.html,在b.html中的window.name賦值保存了一段數(shù)據(jù),但是現(xiàn)在還獲取不了,因為是跨域的,所以,我們可以把src設置為當前域的http://localhost:6000/proxy.html,雖然域名改變了但是window.name是沒有改變的。這樣就可以拿到我們想要的數(shù)據(jù)了。

postMessage(HTML5)

可能很多不知道postMessage整個API,在HTML5中新增了postMessage方法允許來自不同源的腳本采用異步方式進行有限的通信,可以實現(xiàn)跨文本檔、多窗口、跨域消息傳遞,postMessage在很多瀏覽器中都已經(jīng)得到了良好的支持,所以可放心的使用。該方法可以通過綁定windowmessage事件來監(jiān)聽發(fā)送跨文檔消息傳輸內(nèi)容。

postMessage()方法接受兩個參數(shù)

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

origin:字符串參數(shù),指明目標窗口的源,協(xié)議+主機+端口號+URLURL會被忽略,所以可以不寫,這個參數(shù)是為了安全考慮,postMessage()方法只會將message傳遞給指定窗口,當然如果愿意也可以建參數(shù)設置為"*",這樣可以傳遞給任意窗口,如果要指定和當前窗口同源的話設置為"/"。

http://localhost:6000/a.html








http://localhost:7000/b.html








Hello World!

這樣我們就可以接收任何窗口傳遞來的消息了,為了安全起見,我們利用這時候的MessageEvent對象判斷了一下消息源,MessageEvent對象,這個對象中包含很多東西。

data:顧名思義,是傳遞來的message

source:發(fā)送消息的窗口對象

origin:發(fā)送消息窗口的源(協(xié)議+主機+端口號)

使用postMessage方法比以上方法用起來要輕便,不必有太多的繁瑣操作,可以說postMessage是對于解決跨域來說是一個比較好的解決方案,不會顯得代碼特別的臃腫,并且各個瀏覽器又有良好的支持。

跨域資源共享(CORS)

CORS:全稱"跨域資源共享"(Cross-origin resource sharing)。CORS需要瀏覽器和服務器同時支持,才可以實現(xiàn)跨域請求,目前幾乎所有瀏覽器都支持CORSIE則不能低于IE10CORS的整個過程都由瀏覽器自動完成,前端無需做任何設置,跟平時發(fā)送ajax請求并無差異。CORS的關鍵在于服務器,只要服務器實現(xiàn)CORS接口,就可以實現(xiàn)跨域通信。

跨域資源共享(CORS) 是一種機制,它使用額外的HTTP頭來告訴瀏覽器讓運行在一個origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域、協(xié)議或端口請求一個資源時,資源會發(fā)起一個跨域HTTP請求。在上面說過src是不受同源策略限制的,但是出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源HTTP請求。例如,XMLHttpRequestFetchAPI遵循同源策略。這意味著使用這些APIWeb應用程序只能從加載應用程序的同一個域請求HTTP資源,除非響應報文包含了正確CORS響應頭。

所有CORS相關的的頭都是Access-Control為前綴的。下面是每個頭的一些細節(jié)。

字段 描述
Access-Control-Allow-Methods 該字段必需,它的值是逗號分隔的一個字符串,表明服務器支持的所有跨域請求的方法。注意,返回的是所有支持的方法,而不單是瀏覽器請求的那個方法。這是為了避免多次"預檢"請求
Access-Control-Allow-Headers 如果瀏覽器請求包括Access-Control-Request-Headers字段,則Access-Control-Allow-Headers字段是必需的。它也是一個逗號分隔的字符串,表明服務器支持的所有頭信息字段,不限于瀏覽器在"預檢"中請求的字段
Access-Control-Allow-Credentials 該字段與簡單請求時的含義相同。
Access-Control-Max-Age 該字段可選,用來指定本次預檢請求的有效期,單位為秒。上面結(jié)果中,有效期是20天(1728000秒),即允許緩存該條回應1728000秒(即20天),在此期間,不用發(fā)出另一條預檢請求。
import express from "express";
import cors from "cors";

const app = express();
const corsOptions = {
  origin: "http://example.com",
  optionsSuccessStatus: 200
}
 
app.get("/products/:id", cors(corsOptions), (req, res, next) => {
  res.json({msg: "This is CORS-enabled for only example.com."})
})
 
app.listen(80, function () {
  console.log("啟用corba,端口:80")
})

使用CORS簡單請求,非常容易,對于前端來說無需做任何配置,與發(fā)送普通ajax請求無異。唯一需要注意的是,需要攜帶cookie信息時,需要將withCredentials設置為true即可。CORS的配置,完全在后端設置,配置起來也比較容易,目前對于大部分瀏覽器兼容性也比較好,現(xiàn)在應用最多的就是CORS解決跨域了。

在開發(fā)過程中由于各個公司的差異選用的接口風格也是不同的,很多公司會采用RESTful風格去編寫接口,難免就會有些騷操作,在跨域請求時自定義的請求頭是不允許這樣操作的,因為瀏覽器根據(jù)Response Headers判斷請求是否允許。

跨域時默認允許的方法

GET

HEAD

POST

因為瀏覽器希望在網(wǎng)頁進行跨域請求操作的時候是保證服務端的安全的,不允許任何隨便進行跨域,不允許隨便的方法進行跨域,以防數(shù)據(jù)被惡意篡改。所以提供這些限制之后,就可以進行一些非常有利的判斷。針對如上問題需要服務端進行特殊處理才行

const http = request("http");
http.createServer(function(request,response){
    response.writeHead(200,{
        // 設置允許跨域的訪問地址
        "Access-Control-Allow-Origin":"*",
        // 設置允許訪問的自定義請求頭
        "Access-Control-Allow-Headers":"X-Test-Cors",
        // 設置允許跨域的methods
        "Access-Control-Allow-Methods":"POST,Put,Delete",
        // 允許以上三個方式進行跨域的最長時間,1000秒內(nèi)不需要發(fā)送預請求驗證了
        "Access-Control-Max-Age":"1000"
    })
    response.end("123")
}).listen(3000)

這樣設置,這個請求就成功了,但是可以觀測到多了一個請求,這個多出來的請求就是預請求,告訴瀏覽器,這個自定義請求是允許的,然后再正式的發(fā)送這個請求,通過驗證之后就請求成功了,瀏覽器為什么要做這些限制,是因為保證安全,不允許隨便一個人都可以進行跨域。

WebSocket協(xié)議跨域

WebSocketHTML5新推出的一個API,通過WebSocket可以實現(xiàn)客戶端與服務端的即時通信,如聊天室,服務數(shù)據(jù)同步渲染等等。WebSocket是點對點通信,服務端與客戶端可以通過某種標識完成的。WebSocket是不受同源策略限制的所以可以利用這個特性直接與服務端進行點對點通信。

以下示例沒有使用HTML5WebSocket而是使用的socket.io完成類似的功能操作。

若若的說一句:其實我一直以為WebSocketAjax一樣是受同源策略限制的,經(jīng)過學習才發(fā)現(xiàn)不是的。真是學到老活到老(關谷口音)。O(∩_∩)O

服務端:

var io = require("socket.io")(1234);
io.sockets.on("connection", (client) => {
    client.on("message", function (msg) { //監(jiān)聽到信息處理
        client.send("服務器收到了信息:" + msg);
    });
    client.on("disconnect", function () { //斷開處理
        console.log("client has disconnected");
    });
});
console.log("listen 1234...");

客戶端:

$(function () {
    var iosocket = io.connect("http://localhost:1234/");
    var $ul = $("ul");
    var $input = $("input");
    iosocket.on("connect", function () {  //接通處理
        $ul.append($("
  • 連上啦
  • ")); iosocket.on("message", function (message) { //收到信息處理 $ul.append($("
  • ").text(message)); }); iosocket.on("disconnect", function () { //斷開處理 $ul.append("
  • Disconnected
  • "); }); }); $input.keypress(function (event) { if (event.which == 13) { //回車 event.preventDefault(); console.log("send : " + $input.val()); iosocket.send($input.val()); $input.val(""); } }); });

    Websocket既然能支持跨域方法,那就是說,一個開放給公網(wǎng)的Websocket服務任何人都能訪問,這樣的話會使數(shù)據(jù)變得很不安全,所以可以通過對連接域名進行認證即可。

    服務器反代

    學習路程首先了解了一下什么是反代,在計算機網(wǎng)絡中,反向代理是代理服務器的一種。服務器根據(jù)客戶端的請求,從其關聯(lián)的一組或多組后端服務器(如Web服務器)上獲取資源,然后再將這些資源返回給客戶端,客戶端只會得知反向代理的IP地址,而不知道在代理服務器后面的服務器簇的存在。 -- 節(jié)選自百度百科

    反向代理服務器:就nginxhttp請求轉(zhuǎn)發(fā)到另一個或者一些服務器上。從而輕松實現(xiàn)跨域訪問。比如服務器中分別部署了N個服務器,當客戶端發(fā)起請求時不用直接請求服務器中N個節(jié)點上的服務,只需要訪問我們的代理服務器就行了,代理服務器根據(jù)請求內(nèi)容分發(fā)到不同服務器節(jié)點。這僅是一種使用場景,當然還可以做負載均衡等。

    反向代理理解起來不是特別的難,平時生活中最常見的例子,當我們撥打人工客服的時候,并不是直接撥打客服的某一個電話號碼,而是撥打總機號碼,當我們撥打然后由總機進行處理,然后再分發(fā)給不同的客服人員。r然而當服務人員需要讓你掛斷電話等待回撥的時候,也不是直接撥打到你的電話,同樣是也通過總機之后再轉(zhuǎn)發(fā)到你的電話。其實這個總機也就相當于反代服務器。雖然這個例子不太貼切但是多多少少就是這個意思。

    由于不太懂Nginx不知道該如何處理這個部分,只是對反向代理做了一個簡單的了解,等以后學習了Nginx會補上相關代碼。

    Nodejs代理跨域

    使用Nodejs進行跨域在我看來,就是使用Node服務做了一個中間代理轉(zhuǎn)發(fā),其原理和反向代理差不多,當訪問某一個URL時需要通過服務器分發(fā)到另一個服務器URL地址中。這里就不過多的贅述了,直接看代碼吧。

    示例代碼入下:

    main.js

    import http from "http";
    import httpProxy from "http-proxy";
      
    // 新建一個代理 Proxy Server 對象  
    const proxy = httpProxy.createProxyServer({});  
      
    // 捕獲異常  
    proxy.on("error", function (err, req, res) {  
      res.writeHead(500, {  
        "Content-Type": "text/plain"  
      });  
      res.end("error");  
    });  
        
    // 在每次請求中,調(diào)用 proxy.web(req, res config) 方法進行請求分發(fā)  
    const server = http.createServer((req, res) => {  
      // 在這里可以自定義你的路由分發(fā)  
      let host = req.headers.host, ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;  
      switch(host){  
        case "www.a.com":   
            proxy.web(req, res, { target: "http://localhost:3000" });  
            break;  
        case "www.b.com":  
            proxy.web(req, res, { target: "http://localhost:4000" });  
            break;
        default:  
            res.writeHead(200, {  
                "Content-Type": "text/plain"  
            });  
            res.end("Hello Aaron!");  
      }  
    });  
    server.listen(8080);

    如代碼所示,當訪問www.a.com的時候,請求就被轉(zhuǎn)發(fā)到了3000接口上,訪問www.b.com時就被轉(zhuǎn)發(fā)到了4000這個接口上。這樣就簡單的完成了一個反向代理的工作。

    在使用vue開發(fā)的時候難免也會遇到跨域問題,或許你根本就沒有遇到,可能你們正好處于同一個域里面,還有一種可能就是,后端同學或者運維同學已經(jīng)處理好有關跨域的相關操作。但是當在開發(fā)過程中遇到跨域的時候,什么前端應該有對應的解決辦法。vue-cli是基于Node服務的,所以我們可以利用這個服務來做代理工作,暫時解決開發(fā)中的跨域問題。

    build/webpack.config.js

    module.exports = {
        devServer: {
            historyApiFallback: true,
            proxy: [{
                context: "/login",  //  url以/login為開頭時啟用代理
                target: "http://www.a.com:8080",  // 代理跨域目標接口
                changeOrigin: true,
                secure: false,  // 當代理某些https服務報錯時用
                cookieDomainRewrite: "www.b.com"  // 可以為false,表示不修改
            }],
            noInfo: true
        }
    }

    在開發(fā)過程中遇到的可以通過這種方式解決,但是到達生產(chǎn)環(huán)境時到底使用什么方法還是需要斟酌的,畢竟要使服務數(shù)據(jù)變得更加的安全才是最好的。

    總結(jié)

    以上講了很多有關跨域的解決方案,有利也有弊,對于我而言可能更加的傾向于后端粑粑或者運維粑粑去解決跨域問題,畢竟前端處理起來畢竟不是很安全,而且后端或者運維處理起來也不是那么的麻煩。

    很感謝大家利用這么長時間來讀這篇文章,文章中若有錯誤請在下方留言,會盡快做出修改。

    文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/104870.html

    相關文章

    • 【Geek議題】當年那些風騷跨域操作

      摘要:同源策略年,同源政策由公司引入瀏覽器。標簽不受同源策略限制,但只能發(fā)起請求。這一行為使得不同域的特定文檔可以讀取該屬性值,因此可以繞過同源策略并使跨域消息通信成為可能。 前言 現(xiàn)在cross-origin resource sharing(跨域資源共享,下簡稱CORS)已經(jīng)十分普及,算上IE8的不標準兼容(XDomainRequest),各大瀏覽器基本都已支持,當年為了前后端分離、if...

      mengera88 評論0 收藏0
    • 【Geek議題】當年那些風騷跨域操作

      摘要:同源策略年,同源政策由公司引入瀏覽器。標簽不受同源策略限制,但只能發(fā)起請求。這一行為使得不同域的特定文檔可以讀取該屬性值,因此可以繞過同源策略并使跨域消息通信成為可能。 前言 現(xiàn)在cross-origin resource sharing(跨域資源共享,下簡稱CORS)已經(jīng)十分普及,算上IE8的不標準兼容(XDomainRequest),各大瀏覽器基本都已支持,當年為了前后端分離、if...

      Worktile 評論0 收藏0
    • 老生常談跨域問題JSONP解決方式

      摘要:解決方案跨域問題可以說在前端方面不可避免,但同源策略畢竟在保護網(wǎng)絡信息安全方面起到很大的作用。 起因 說起來源...今天去茶水間倒水時,偶然聽到公司面試官在問面試者前端跨域的如何解決。我心中默默想了一想,啪啪啪瞬間想出幾個關鍵詞,iframe,cors,同源策略,jsonp...轉(zhuǎn)念一想,雖然這是很常見的面試題,然而我在開發(fā)過程中,還真沒有用過jsonp這種方式...就連原理也說不好。...

      asoren 評論0 收藏0
    • 老生常談跨域問題JSONP解決方式

      摘要:解決方案跨域問題可以說在前端方面不可避免,但同源策略畢竟在保護網(wǎng)絡信息安全方面起到很大的作用。 起因 說起來源...今天去茶水間倒水時,偶然聽到公司面試官在問面試者前端跨域的如何解決。我心中默默想了一想,啪啪啪瞬間想出幾個關鍵詞,iframe,cors,同源策略,jsonp...轉(zhuǎn)念一想,雖然這是很常見的面試題,然而我在開發(fā)過程中,還真沒有用過jsonp這種方式...就連原理也說不好。...

      jemygraw 評論0 收藏0
    • 用 Nokitjs 解決前端開發(fā)中跨域問題

      摘要:用解決問題是一個,和等框架類似,用于開發(fā)應用或網(wǎng)站,這里不去比較各個框架的優(yōu)劣,而是去解決跨域問題。 問題 在開發(fā)一些「單頁應用」時,通常會使用 Ajax 和服務器通訊,比如 RESTful API,通常「前端」和「服務端 API」可能是有不同人員在負責,也不在同一個工程下,那么開發(fā)過程中就可能會遇到跨域的問題,比如 Chrome 會在 console 中看到這樣的錯誤消息: XMLH...

      voidking 評論0 收藏0

    發(fā)表評論

    0條評論

    galois

    |高級講師

    TA的文章

    閱讀更多
    最新活動
    閱讀需要支付1元查看
    <