【网络安全】浅析跨域原理及如何实现跨域
前言
我們在解決一個問題的時候應該先去了解這個問題是如何產生的,為什么會有跨域的存在呢?其實,最終的罪魁禍首都是瀏覽器的同源策略,瀏覽器的同源策略限制我們只能在相同的協議、IP地址、端口號相同,如果有任何一個不通,都不能相互的獲取數據。并且,http和https之間也存在跨域,因為https一般采用的是443端口,http采用的是80端口或者其他。
同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSRF等攻擊。所謂同源是指"協議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
同源策略限制內容有:
1.Cookie、LocalStorage、IndexedDB 等存儲性內容
2.DOM 節點
3.AJAX 請求發送后,結果被瀏覽器攔截了
但是有三個標簽是允許跨域加載資源:
<img src=XXX><link href=XXX><script src=XXX>常見的跨域場景
需要網絡安全資料的朋友可以私信回復“資料”獲取【點擊查看】
當**協議、子域名、主域名、端口號中任意一個不相同時,**都算作不同域。不同域之間相互請求資源,就算作“跨域”。常見跨域場景如下圖所示:
其實,跨域并不是請求發不出去,請求能發出去,服務端能收到請求并正常返回結果,只是結果被瀏覽器攔截了,常見的9種跨域方案,主要有: 通過jsonp跨域、 document.domain + iframe跨域、 location.hash + iframe、window.name + iframe跨域、postMessage跨域、跨域資源共享(CORS)、nginx代理跨域、nodejs中間件代理跨域、WebSocket協議跨域9種,并有著各自獨特的跨域原理。
一:JSONP實現跨域
原理:jsonp實現跨域的原理是跨域的服務端把客戶端所需要的數據放進客戶端本地的一個js方法里,進行調用,客戶端在本地的js對返回的數據進行處理。這樣就實現了不同域名下的兩個站點間的交流。
JSONP優點是簡單兼容性好,可用于解決主流瀏覽器的跨域數據訪問的問題。缺點是僅支持get方法具有局限性,不安全可能會遭受XSS攻擊。
JSONP的實現流程:
- 聲明一個回調函數,其函數名(如show)當做參數值,要傳遞給跨域請求數據的服務器,函數形參為要獲取目標數據(服務器返回的data)。
- 創建一個{script}標簽,把那個跨域的API數據接口地址,賦值給script的src,還要在這個地址中向服務器傳遞該函數名(可以通過問號傳參:?callback=show)。
- 服務器接收到請求后,需要進行特殊的處理:把傳遞進來的函數名和它需要給你的數據拼接成一個字符串,例如:傳遞進去的函數名是show,它準備好的數據是show(‘我不愛你’)。
- 最后服務器把準備的數據通過HTTP協議返回給客戶端,客戶端再調用執行之前聲明的回調函數(show),對返回的數據進行操作。
二:iframe+document.domain跨域
此方法的思想就是設置頁面的document.domain把他們設置成相同的域名,比如都設置成xxx.com,這樣來繞過同源策略。
代碼里面的測試案列是,前端文件在7777端口,后臺文件在8888端口,前端如果需要請求后端的數據就存在跨域,所以我們在后端8888端口寫一個提供數據的中轉html,然后通過ajax或者其他的方法請求到數據,然后把數據往外暴露,此方法需要2個html都需要設置相同的主域。
三:location.hash+iframe跨域
這種方法是一個很奇妙的方法,比如有一個這樣的url:http://www.xxx.com#abc=123,那么我們通過執行location.hash就可以得到這樣的一個字符串#abc=123,同時改變hash頁面是不會刷新的。
假如現在我們有A頁面在7777端口(前端顯示的文件),B頁面在8888端口,后臺運行在8888端口。我們在A頁面中通過iframe嵌套B頁面。
從A頁面要傳數據到B頁面
我們在A頁面中通過,修改iframe的src的方法來修改hash的內容。然后在B頁面中添加setInterval事件來監聽我們的hash是否改變,如果改變那么就執行相應的操作。比如像后臺服務器提交數據或者上傳圖片這些。
從B頁面傳遞數據到A頁面
經過上面的方法,那么肯定有聰明的朋友就在想那么,從B頁面向A頁面發送數據就是修改A頁面的hash值了。對沒錯方法就是這樣,但是我在執行的時候會出現一些問題。我們在B頁面中直接:parent.location.hash = “#xxxx”
這樣是不行的,因為前面提到過的同源策略不能直接修改父級的hash值,所以這里采用了一個我認為很巧妙的方法。部分代碼:
如果可以直接修改我們就直接修改,如果不能直接修改,那么我們在B頁面中再添加一個iframe然后指向C頁面(我們暫時叫他代理頁面,此頁面和A頁面是在相同的一個域下面),我們可以用同樣的方法在url后面我們需要傳遞的信息。在代理頁面中:parent.parent.location.hash = self.location.hash.substring(1);
只需要寫這樣的一段js代碼就完成了修改A頁面的hash值,同樣在A頁面中也添加一個setInterval事件來監聽hash值的改變。
實現的核心思路就是通過修改URL的hash值,然后用定時器來監聽值的改變來修改。所以說最大的問題就是,我們傳遞的數據會直接在URL里面顯示出來,不是很安全,同時URL的長度是一定的所以傳輸的數據也是有限的。
四:window.name+iframe跨域
原理就是window.name屬性在于加載不同的頁面(包括域名不同的情況下),如果name值沒有修改,那么它將不會變化,并且這個值可以非常的長(2MB)
方法原理:A頁面通過iframe加載B頁面。B頁面獲取完數據后,把數據賦值給window.name。然后在A頁面中修改iframe使他指向本域的一個頁面。這樣在A頁面中就可以直接通過iframe.contentWindow.name獲取到B頁面中獲取到的數據。
五:postMessage跨域
postMessage是HTML5引入的API。他可以解決多個窗口之間的通信(包括域名的不同)。我個人認為他算是一種消息的推送,可以給每個窗口推送。然后在目標窗口添加message的監聽事件。從而獲取推送過來的數據。
六:跨域資源共享(CORS)
其實對于跨域資源的請求,瀏覽器已經把我們的請求發放給了服務器,瀏覽器也接受到了服務器的響應,只是瀏覽器一看我們2個的域不一樣就把消息給攔截了,不給我們顯示。所以我們如果我們在服務器就告訴瀏覽器我這個數據是每個源都可以獲取就可以了。這就是CORS跨域資源共享。
這樣的話,任何源都可以通過AJAX發起請求來獲取我們提供的數據。針對不同語言的服務器后端有不一樣的處理方法,但是實質是一樣的。
七:NGINX代理跨域
· nginx配置解決iconfont跨域
瀏覽器跨域訪問js、css、img等常規靜態資源被同源策略許可,但iconfont字體文件(eot|otf|ttf|woff|svg)例外,此時可在nginx的靜態資源服務器中加入以下配置。
location / {add_header Access-Control-Allow-Origin *;}· nginx反向代理接口跨域
跨域原理:同源策略是瀏覽器的安全策略,不是HTTP協議的一部分。服務器端調用HTTP接口只是使用HTTP協議,不會執行JS腳本,不需要同源策略,也就不存在跨越問題。
實現思路:通過nginx配置一個代理服務器(域名與domain1相同,端口不同)做跳板機,反向代理訪問domain2接口,并且可以順便修改cookie中domain信息,方便當前域cookie寫入,實現跨域登錄。
nginx具體配置:
#proxy服務器server{listen 81;server_name www.domain1.com;location/ {proxy_pass http://www.domain2.com:8080; #反向代理proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名index index.html index.htm;# 當用webpack-dev-server等中間件代理接口訪問nignx時,此時無瀏覽器參與,故沒有同源限制,下面的跨域配置可不啟用add_header Access-Control-Allow-Origin http://www.domain1.com; #當前端只跨域不帶cookie時,可為*add_header Access-Control-Allow-Credentials true;}}八:nodejs跨域
其實這種辦法和上一種用nginx的方法是差不多的。都是你把請求發給一個中間人,由于中間人沒有同源策略,他可以直接代理或者通過爬蟲或者其他的手段得到想到的數據,然后返回(是不是和VPN的原理有點類似)。
當然現在常見的就是用nodejs作為數據的中間件,同樣,不同的語言有不同的方法,但是本質是一樣的。我上次自己同構自己的博客頁面,用react服務器端渲染,因為瀏覽器的同源策略,請求不到數據,然后就用了nodejs作為中間件來代理請求數據。
九:webSocket跨域
webSocket大家應該都有所耳聞,主要是為了客服端和服務端進行全雙工的通信。但是這種通信是可以進行跨端口的。所以說我們可以用這個漏洞來進行跨域數據的交互。
所以說,我們可以很輕松的構建基于webSocket構建一個客服端和服務端。代碼在github建議大家都多多去運行一下,了解清楚。
總結
以上是生活随笔為你收集整理的【网络安全】浅析跨域原理及如何实现跨域的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【安全漏洞】CVE-2021-32682
- 下一篇: 【网络安全】红蓝攻防:shellcode