什么是跨域咆蒿?
跨域是指a頁面想獲取b頁面資源东抹,如果a、b頁面的協(xié)議沃测、域名缭黔、端口、子域名不同蒂破,或是a頁面為ip地址馏谨, b頁面為域名地址,所進行的訪問行動都是跨域
產(chǎn)生的原因附迷?
瀏覽器為了安全問題一般都限制了跨域訪問惧互,也就是不允許跨域請求資源
同ip(或domain),同端口,同協(xié)議視為同一個域挟秤,一個域內(nèi)的腳本僅僅具有本域內(nèi)的權(quán)限壹哺,可以理解為本域腳本只能讀寫 本域內(nèi)的資源,而無法訪問其它域的資源艘刚。這種安全限制稱為同源策略
現(xiàn)代瀏覽器在安全性和可用性之間選擇了一個平衡點管宵。 在遵循同源策略的基礎(chǔ)上,選擇性地為同源策略“開放了后門”。例如img script style等標簽箩朴,都允許垮域引用資源,然而岗喉, 你也只能是引用這些資源而已,并不能讀取這些資源的內(nèi)容
同源策略限制以下幾種行為:
1.Cookie炸庞、LocalStorage 和 IndexDB 無法讀取
2.DOM 和 Js對象無法獲得
3.AJAX 請求不能發(fā)送
常見跨域場景
http://www.domain.com/a.jshttp://www.domain.com/b.js 同一域名钱床,不同文件或路徑 允許http://www.domain.com/lab/c.jshttp://www.domain.com:8000/a.jshttp://www.domain.com/b.js 同一域名,不同端口 不允許http://www.domain.com/a.jshttps://www.domain.com/b.js 同一域名埠居,不同協(xié)議 不允許http://www.domain.com/a.jshttp://192.168.4.12/b.js 域名和域名對應(yīng)相同ip 不允許http://www.domain.com/a.jshttp://x.domain.com/b.js 主域相同查牌,子域不同 不允許http://domain.com/c.jshttp://www.domain1.com/a.jshttp://www.domain2.com/b.js 不同域名 不允許
跨域解決方案
1、 通過jsonp跨域
2滥壕、 document.domain + iframe跨域
3纸颜、 location.hash + iframe
4、 window.name + iframe跨域
5绎橘、 postMessage跨域
6胁孙、 跨域資源共享(CORS)
7、 nginx代理跨域
8称鳞、 nodejs中間件代理跨域
9涮较、 WebSocket協(xié)議跨域
nginx反向代理解決跨域
正向代理:代理位于網(wǎng)站和客戶端中間, 客戶端無法訪問某網(wǎng)站冈止,就將請求發(fā)送給代理服務(wù)器狂票,代理從網(wǎng)站取回來再發(fā)送給客戶端,網(wǎng)站并不知道為誰提供服務(wù)
反向代理:客戶端訪問某網(wǎng)站的一個頁面靶瘸, 但是網(wǎng)站并沒有苫亦,就偷偷從另外一臺服務(wù)器上取回來,然后作為自己的內(nèi)容吐給用戶,用戶不知道真正提供服務(wù)的是誰
對于瀏覽器來說怨咪,訪問的就是同源服務(wù)器上的一個url屋剑。而nginx通過 檢測url前綴,把http請求轉(zhuǎn)發(fā)到后面真實的物理服務(wù)器诗眨。并通過rewrite命令把前綴再去掉唉匾。這樣真實的服務(wù)器就可以正確 處理請求,并且并不知道這個請求是來自代理服務(wù)器的匠楚。
簡單說巍膘,nginx服務(wù)器欺騙了瀏覽器,讓它認為這是同源調(diào)用芋簿,從而解決了瀏覽器的跨域問題峡懈。又通過重寫url,欺騙了真實 的服務(wù)器与斤,讓它以為這個http請求是直接來自與用戶瀏覽器的肪康。
Location/carrots-admin-ajax/{
????proxy_passhttp://dev.admin.carrots.ptteng.com/;
}
proxy_pass把請求代理到其他主機
兩種寫法hhttp://dev.admin.carrots.ptteng.com/? ? 和? ? ?http://dev.admin.carrots.ptteng.com
????如果訪問url =http://server/html/test.jsp荚恶,則被nginx代理后
? ? ? ? 情況1,將test/作為根路徑磷支,請求test/路徑下的資源谒撼。
? ? ? ? 情況2,則被nginx代理后雾狈,請求路徑會變?yōu)閔ttp://proxy_pass/test.jsp廓潜,直接訪問server的根資源。
/carrots-admin-ajax/
是一個匹配規(guī)則善榛,用于攔截請求辩蛋,匹配任何以/proxy/html/開頭的地址,匹配符合以后移盆,停止往下搜索正則堪澎。
對于瀏覽器來說,訪問的就是同源服務(wù)器上的一個url味滞。而nginx通過檢測url前綴,把http請求轉(zhuǎn)發(fā)到后面真實的物理服務(wù)器钮呀。并通過rewrite命令把前綴再去掉剑鞍。這樣真實的服務(wù)器就可以正確處理請求,并且并不知道這個請求是來自代理服務(wù)器的爽醋。
簡單說蚁署,nginx服務(wù)器欺騙了瀏覽器,讓它認為這是同源調(diào)用蚂四,從而解決了瀏覽器的跨域問題光戈。又通過重寫url,欺騙了真實的服務(wù)器遂赠,讓它以為這個http請求是直接來自與用戶瀏覽器的久妆。
nginx rewrite指令執(zhí)行順序:
1.執(zhí)行server塊的rewrite指令(這里的塊指的是server關(guān)鍵字后{}包圍的區(qū)域,其它xx塊類似)
2.執(zhí)行l(wèi)ocation匹配
3.執(zhí)行選定的location中的rewrite指令
如果其中某步URI被重寫跷睦,則重新循環(huán)執(zhí)行1-3筷弦,直到找到真實存在的文件
如果循環(huán)超過10次,則返回500 Internal Server Error錯誤
7.參考文獻
參考一:https://www.cnblogs.com/gabrielchen/p/5066120.html
參考二:http://blog.csdn.net/shendl/article/details/48443299
8.更多討論
提問:
Q:例如img script style等標簽抑诸,都允許垮域引用資源烂琴?
A:在瀏覽器中,并且加載的方式其實相當(dāng)于一次普通的GET請求蜕乡,唯一不同的是奸绷,為了安全起見攻锰,瀏覽器不允許這種方式下對加載到的資源的讀寫操作挑胸,而只能使用標簽本身應(yīng)當(dāng)具備的能力(比如腳本執(zhí)行、樣式應(yīng)用等等)巴碗。
Q:例如img script style等標簽,都允許垮域引用資源扣癣?
A:在瀏覽器中惰帽,并且加載的方式其實相當(dāng)于一次普通的GET請求,唯一不同的是父虑,為了安全起見该酗,瀏覽器不允許這種方式下對加載到的資源的讀寫操作,而只能使用標簽本身應(yīng)當(dāng)具備的能力(比如腳本執(zhí)行士嚎、樣式應(yīng)用等等)呜魄。
Q:JSONP和nginx跨域有什么不同
JSONP和nginx是完全不同的 是可以跨域的,而且在跨域腳本中可以直接回調(diào)當(dāng)前腳本的函數(shù)
原理:是可以跨域的莱衩,而且在跨域腳本中可以直接回調(diào)當(dāng)前腳本的函數(shù)
script標簽是可以加載異域的JavaScript并執(zhí)行的爵嗅,通過預(yù)先設(shè)定好的callback函數(shù)來實現(xiàn)和母頁面的交互。它有一個大名笨蚁,叫做JSONP跨域睹晒,JSONP是JSON with Padding的略稱。它是一個非官方的協(xié)議括细,明明是加載script伪很,為啥和JSON扯上關(guān)系呢?原來就是這個callback函數(shù)奋单,對它的使用有一個典型的方式锉试,就是通過JSON來傳參,即將JSON數(shù)據(jù)填充進回調(diào)函數(shù)览濒,這就是JSONP的JSON+Padding的含義呆盖。JSONP只支持GET請求。