日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
前端開發(fā)|那些年曾談起的跨域

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

創(chuàng)新互聯(lián)從2013年成立,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目成都做網(wǎng)站、成都網(wǎng)站制作網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元麻山做網(wǎng)站,已為上家服務,為麻山各地企業(yè)和個人服務,聯(lián)系電話:13518219792

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

什么同源策略

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

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

Url組成部分

了解同源策略以后,同樣需要對url的組成部分也順帶了解一下吧,只有了解url之后當出現(xiàn)跨域的時候才知道哪里出了問題,這樣才能和后端、運維開懟,懟天懟地對空氣。O(∩_∩)O哈哈~

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

  1. protocol:協(xié)議常用的協(xié)議是http
  2. auth:驗證,因為明文傳輸用戶名和密碼,非HTTPS環(huán)境下很不安全,一般用的非常少
  3. hostname:主機地址,可以是域名,也可以是IP地址
  4. port:端口http協(xié)議默認端口是:80端口,如果不寫默認就是:80端口
  5. pathname:路徑網(wǎng)絡資源在服務器中的指定路徑
  6. serarch:查詢字符串如果需要從服務器那里查詢內(nèi)容,在這里編輯
  7. hash:哈希網(wǎng)頁中可能會分為不同的片段,如果想訪問網(wǎng)頁后直接到達指定位置,可以在這部分設置

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

  1. Cookie、LocalStorage和IndexDB等無法讀取。
  2. DOM無法獲得。
  3. AJAX請求不能發(fā)送。

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

  1.   
  2.   
  3.   

http://localhost:7000/b.html 

 
 
 
 
  1.   
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
  8.   
  9.   
  10.   

http://localhost:6000/c.html 

 
 
 
 
  1.   
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
  8.   
  9.   
  10.   

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

window.name

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

http://localhost:6000/a.html 

 
 
 
 
  1.   
  2.   

http://localhost:7000/b.html 

 
 
 
 
  1. var person = {  
  2.   name: 'Aaron',  
  3.   age: 18  
  4. }  
  5. window.name = JSON.stringify(person)  

http://localhost:6000/proxy.html 

 
 
 
 
  1.   
  2.   
  3.   
  4.   
  5. proxy  
  6.   
  7.   
  8. 這是proxy頁面

      
  9.   
  10.   

在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)得到了良好的支持,所以可放心的使用。該方法可以通過綁定window的message事件來監(jiān)聽發(fā)送跨文檔消息傳輸內(nèi)容。

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

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

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

http://localhost:6000/a.html 

 
 
 
 
  1.   
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
  8.   
  9.       
  10.     發(fā)送消息  
  
  •   
  •   
  •   
  •   
  • http://localhost:7000/b.html 

     
     
     
     
    1.   
    2.   
    3.   
    4.   
    5.   
    6.   
    7.   
    8.   
    9.     Hello World!  
      
  •   
  •   
  •   
  • 這樣我們就可以接收任何窗口傳遞來的消息了,為了安全起見,我們利用這時候的MessageEvent對象判斷了一下消息源,MessageEvent對象,這個對象中包含很多東西。

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

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

    跨域資源共享(CORS)

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

    跨域資源共享(CORS) 是一種機制,它使用額外的HTTP頭來告訴瀏覽器讓運行在一個origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域、協(xié)議或端口請求一個資源時,資源會發(fā)起一個跨域HTTP請求。在上面說過src是不受同源策略限制的,但是出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源HTTP請求。例如,XMLHttpRequest和FetchAPI遵循同源策略。這意味著使用這些API的Web應用程序只能從加載應用程序的同一個域請求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該字段可選,用來指定本次預檢請求的有效期,單位為秒。上面結果中,有效期是20天(1728000秒),即允許緩存該條回應1728000秒(即20天),在此期間,不用發(fā)出另一條預檢請求。

     

     
     
     
     
    1. import express from "express";  
    2. import cors from "cors";  
    3. const app = express()  
    4. const  
    5. var corsOptions = {  
    6.   origin: 'http://example.com',  
    7.   optionsSuccessStatus: 200  
    8. }  
    9. app.get('/products/:id', cors(corsOptions), (req, res, next) => {  
    10.   res.json({msg: 'This is CORS-enabled for only example.com.'})  
    11. })  
    12. app.listen(80, function () {  
    13.   console.log('啟用corba,端口:80')  
    14. })  

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

    WebSocket協(xié)議跨域

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

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

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

    服務端: 

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

    客戶端: 

     
     
     
     
    1. $(function () {  
    2.     var ioiosocket = io.connect('http://localhost:1234/');  
    3.     var $ul = $("ul");  
    4.     var $input = $("input");  
    5.     iosocket.on('connect', function () {  //接通處理  
    6.         $ul.append($('
    7. 連上啦
    8. '));  
    9.         iosocket.on('message', function (message) {  //收到信息處理  
    10.             $ul.append($('
    11. ').text(message));  
    12.         });  
    13.         iosocket.on('disconnect', function () { //斷開處理  
    14.             $ul.append('
    15. Disconnected
    16. ');  
    17.         });  
    18.     });  
    19.     $input.keypress(function (event) {  
    20.         if (event.which == 13) { //回車  
    21.             event.preventDefault();  
    22.             console.log("send : " + $input.val());  
    23.             iosocket.send($input.val());  
    24.             $input.val('');  
    25.         }  
    26.     });  
    27. });  

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

    服務器反代

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

    反向代理服務器:就nginx把http請求轉(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 

     
     
     
     
    1. import http from "http";  
    2. import httpProxy from "http-proxy";  
    3. // 新建一個代理 Proxy Server 對象    
    4. const proxy = httpProxy.createProxyServer({});     
    5. // 捕獲異常    
    6. proxy.on('error', function (err, req, res) {    
    7.   res.writeHead(500, {    
    8.     'Content-Type': 'text/plain'    
    9.   });    
    10.   res.end('error');    
    11. });       
    12. // 在每次請求中,調(diào)用 proxy.web(req, res config) 方法進行請求分發(fā)    
    13. const server = http.createServer((req, res) => {   
    14.   // 在這里可以自定義你的路由分發(fā)    
    15.   let host = req.headers.host, ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;    
    16.   switch(host){    
    17.     case 'www.a.com':     
    18.         proxy.web(req, res, { target: 'http://localhost:3000' });    
    19.         break;    
    20.     case 'www.b.com':    
    21.         proxy.web(req, res, { target: 'http://localhost:4000' });    
    22.         break;  
    23.     default:    
    24.         res.writeHead(200, {    
    25.             'Content-Type': 'text/plain'    
    26.         });    
    27.         res.end('Hello Aaron!');    
    28.   }    
    29. });    
    30. 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ā)|那些年曾談起的跨域
    本文地址:http://m.5511xx.com/article/coipccg.html