摘要:跨域的產生不用多講,作為一名前端開發人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的。瀏覽器引入同源策略主要是為了防止,攻擊。其指明了實際請求所允許使用的方法。
跨域,相信大家無論是在工作中還是在面試中經常遇到這個問題,常常在網上看到別人所整理的一些方法,看似知道是怎么回事,但如果沒有動手實踐過,總覺得自己沒有真正的掌握,在這里,通過自己認真思考整理一些常用的方法。跨域的產生
不用多講,作為一名前端開發人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的。所謂同源是指"協議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。瀏覽器引入同源策略主要是為了防止XSS,CSRF攻擊。
CSRF(Cross-site request forgery),跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。
在同源策略影響下,域名A向域名B發送Ajax請求,或操作Cookie、LocalStorage、indexDB等數據,或操作dom,js就會受到限制,但請求css,js等靜態資源不受限制
跨域的解決方案 1 通過jsonp跨域首先說一下jsonp的原理,例如我們平時寫html的時候常常會使用
這種方式去取放在另外服務器上的靜態資源,這個是不受同源策略所限制的,所以我們利用這一點可以解決跨域的問題。
主要代碼如下:
1.1原生實現在www.a.com域名寫下如下代碼,去請求www.b.com域名的數據
這里,我們利用動態腳本的src屬性,變相地發送了一個http://www.b.com/getdata?call...。這時候,b.com頁面接受到這個請求時,如果沒有JSONP,會正常返回json的數據結果,像這樣:{ msg: "helloworld" },而利用JSONP,服務端會接受這個callback參數,然后用這個參數值包裝要返回的數據:demo({msg: "helloworld"});
這時候,如果a.com的頁面上正好有一個demo 的函數:
function demo(res){
console.log(res);
}
當遠程數據一返回的時候,隨著動態腳本的執行,這個demo函數就會被執行。
1.2 jquery ajax請求實現$.ajax({ url:"http://www.b.com/getdata", type:"get", dataType: "jsonp", // 請求方式為jsonp jsonpCallback: "demo", // 自定義回調函數名 data: {} });服務端代碼實現:
以nodejs為例
var http = require(http); //引入url模塊解析url字符串 var url = require("url); //引入querystring模塊處理query字符串 var querystring = require("querystring"); var server = http.createServer(); server.on("request",function(req,res){ var urlPath = url.parse(req.url).pathname; var param = querystring .parse(req.url.split("?")[1]); if(urlPath === "/getData" && param.callback) { res.writeHead(200,{"Content-Type","application/json;charset=utf-8"}); var data = { msg: "helloworld" }; data = JSON.stringify(data ); var callback = param .callback+"("+data+");"; res.write(callback); res.end(); } else { res.writeHead(200, {"Content-Type":"text/html;charset=utf-8"}); res.write("Hell World "); res.end(); } })
jsonp缺點:只能使用get請求,不推薦使用2 CORS 跨域資源共享
跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。2.1 簡單請求和非簡單請求Cross-Origin Resource Sharing跨域資源共享,應該算是現在比較推薦的跨域處理方案.不僅適用于各種Method,而且更加方便和簡單
目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。
瀏覽器將CORS請求分成兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。
簡單請求同時滿足以下條件,只要不滿足以下條件的則為非簡單請求
非簡單請求會發出一次預檢測請求,返回碼是204,預檢測通過才會真正發出請求,這才返回200。這里通過前端發請求的時候增加一個額外的headers來觸發非簡單請求。2.2 進行帶有身份憑證的CORS 請求
默認情況下的跨域請求都是不會把cookie發送給服務器的,在需要發送的情況下,如果是xhr,那么需要設置xhr.withCredentials=true,
如果是采用fetch獲取的話,那么需要在request里面設置 credentials:"include",
但是如果服務器在預請求的時候沒返回Access-Control-Allow-Crenditials:true的話,那么在實際請求的時候,cookie是不會被發送給服務器端的,要特別注意對于簡單的get請求,不會有預請求的過程,
那么在實際請求的時候,如果服務器沒有返回Access-Control-Allow-Crenditials:true的話那么響應結果瀏覽器也不會交給請求者
對于附帶身份憑證的請求,服務器不得設置 Access-Control-Allow-Origin 的值為“*”。2.3 HTTP 響應首部字段這是因為請求的首部中攜帶了 Cookie 信息,如果 Access-Control-Allow-Origin
的值為“*”,請求將會失敗。而將 Access-Control-Allow-Origin 的值設置為
http://www.a.com,則請求將成功執行。
Access-Control-Allow-Origin:
Access-Control-Expose-Headers 頭讓服務器把允許瀏覽器訪問的頭放入白名單
Access-Control-Max-Age 頭指定了preflight請求的結果能夠被緩存多久
Access-Control-Allow-Credentials
頭指定了當瀏覽器的credentials設置為true時是否允許瀏覽器讀取response的內容。
Access-Control-Allow-Methods 首部字段用于預檢請求的響應。其指明了實際請求所允許使用的 HTTP 方法。
Access-Control-Allow-Headers 首部字段用于預檢請求的響應。其指明了實際請求中允許攜帶的首部字段。
2.4 以nodejs express為例,說明如何使用cors解決跨域var express=require("express"); var url=require("url"); var app=express(); var allowCrossDomain = function(req, res, next) { res.header("Access-Control-Allow-Origin", "http://localhost:63342"); res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE"); res.header("Access-Control-Allow-Headers", "Content-Type"); res.header("Access-Control-Allow-Credentials","true"); next(); }; app.use(allowCrossDomain); app.get("/getData",function (req,res,next) { var queryValue=url.parse(req.url).query; if(queryValue==="fortunewheel@sina.com"){ res.send(true); }else { res.send(false); } }); app.listen(3001);
實際開發過程中,為了安全,會和token一起使用3 window.postMessage
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是為數不多可以跨域操作的window屬性之一,它可用于解決以下方面的問題:
iframe嵌套頁面跨域通信
頁面和其打開的新窗口的通信
多窗口之間消息傳遞
用法:
postMessage(data,origin)方法接受兩個參數,
data:需要傳遞的數據,html5規范支持任意基本類型或可復制的對象,但部分瀏覽器只支持字符串,所以傳參時最好用JSON.stringify()序列化。
origin:協議+主機+端口號,也可以設置為"*",表示可以傳遞給任意窗口,如果要指定和當前窗口同源的話設置為"/"。
代碼示例:
http://www.a.com/a.html
http://www.b.com/b.html
4 document.domain這種方式只適合主域名相同,但子域名不同的iframe跨域。
實現原理:兩個頁面都通過js強制設置document.domain為基礎主域,就實現了同域。
使用方式:
http://www.a.com/a.html
"http://www.child.a.com/b.html
5 window.namewindow.name 傳輸技術的基本原理:
當在瀏覽器中打開一個頁面,或者在頁面中添加一個iframe時即會創建一個對應的window對象,當頁面加載另一個新的頁面時,window.name的屬性是不會變的。這樣就可以利用在頁面動態添加一個iframe然后加載數據頁面,在數據頁面將需要的數據賦值給window.name。然而此時承載的iframe的parent頁面還是不能直接訪問不在同一域下的iframe的那么屬性,這時,只需要將iframe再加載一個與承載頁面同域的空白頁面,即可對window.name進行數據讀取。
通過iframe的src屬性由外域轉向本地域,跨域數據即由iframe的window.name從外域傳遞到本地域。這個就巧妙地繞過了瀏覽器的跨域訪問限制,但同時它又是安全操作。
具體實現:
http://www.a.com/a.html 主頁面
http://www.b.com/b.html 數據頁面
http://www.a.com/proxy.html 代理頁面
http://www.a.com/a.html代碼:
http://www.b.com/b.html代碼:
window.name = "123"
http://www.a.com/proxy.html空白
6 nginx代理跨域server{ # 監聽8080端口 listen 8080; # 域名是localhost server_name localhost; #凡是localhost:8080/api這個樣子的,都轉發到真正的服務端地址http://www.b.com:8080 location ^~ /api { proxy_pass http://www.b.com:8080; } }
配置之后就不需要前端做什么修改了,一般我們在前后端分離項目中開發階段會采用這種方式,但不是所有場景都能這樣做,例如后端接口是一個公共的API,比如一些公共服務獲取天氣什么的。7 WebSocket協議跨域
websoket協議天然支持跨域,你只需要學會如何使用它即可,關于websocket協議請看我的另外一篇文章WebSocket網絡通信協議
參考文章:
https://developer.mozilla.org...
https://segmentfault.com/a/11...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/117027.html
摘要:跨域的產生不用多講,作為一名前端開發人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的。瀏覽器引入同源策略主要是為了防止,攻擊。其指明了實際請求所允許使用的方法。 跨域,相信大家無論是在工作中還是在面試中經常遇到這個問題,常常在網上看到別人所整理的一些方法,看似知道是怎么回事,但如果沒有動手實踐過,總覺得自己沒有真正的掌握,在這里,通過自己認真思考整理一些常用的方法。 跨域的產生 ...
摘要:跨域的產生不用多講,作為一名前端開發人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的。瀏覽器引入同源策略主要是為了防止,攻擊。其指明了實際請求所允許使用的方法。 跨域,相信大家無論是在工作中還是在面試中經常遇到這個問題,常常在網上看到別人所整理的一些方法,看似知道是怎么回事,但如果沒有動手實踐過,總覺得自己沒有真正的掌握,在這里,通過自己認真思考整理一些常用的方法。 跨域的產生 ...
摘要:因為同源策略的限制,我們不能在與外部服務器進行通信的時候使用。這個是跨域服務器取數據的接口,參數為回調函數的名字,返回的格式為原理首先在客戶端注冊一個然后把的名字傳給服務器。 一、同源策略 同源策略,它是由Netscape提出的一個著名的安全策略,現在所有的可支持javascript的瀏覽器都會使用這個策略。 為什么需要同源策略,這里舉個例子: 假設現在沒有同源策略,會發生什么事...
摘要:同源策略做了很嚴格的限制,但是在實際的場景中,又確實有很多地方需要突破同源策略的限制,也就是我們常說的跨域。使用跨域由于同源策略,一般來說位于的網頁無法與不是的服務器溝通,而的元素是一個例外。 本菜雞最近在寫某個頁面請求數據時,報了如下的錯誤。 Failed to load https://...:No Access-Control-Allow-Origin header is pre...
閱讀 2971·2021-09-22 15:18
閱讀 3394·2019-08-30 15:54
閱讀 3273·2019-08-30 15:53
閱讀 587·2019-08-30 14:12
閱讀 813·2019-08-29 17:01
閱讀 2197·2019-08-29 14:04
閱讀 1377·2019-08-29 13:09
閱讀 860·2019-08-26 17:40