摘要:瀏覽器同源策略我們?yōu)楹我芯靠缬騿栴}因?yàn)闉g覽器的同源策略規(guī)定某域下的客戶端在沒明確授權(quán)的情況下,不能讀寫另一個(gè)域的資源。
跨域,老生常談的問題 簡(jiǎn)述
作為一只前端菜鳥,跨域方面只懂得JSONP和CORS,并未曾深入了解。但隨著春招越來(lái)越近,就算是菜鳥也要猛振翅膀。近幾日仔細(xì)研究了跨域問題,寫下這篇文章,希望對(duì)開發(fā)者們有所幫助。在讀本文前,希望您對(duì)以下知識(shí)略有了解。
瀏覽器同源策略
nodejs
iframe
docker, nginx
我們?yōu)楹我芯靠缬騿栴}因?yàn)闉g覽器的同源策略規(guī)定某域下的客戶端在沒明確授權(quán)的情況下,不能讀寫另一個(gè)域的資源。而在實(shí)際開發(fā)中,前后端常常是相互分離的,并且前后端的項(xiàng)目部署也常常不在一個(gè)服務(wù)器內(nèi)或者在一個(gè)服務(wù)器的不同端口下。前端想要獲取后端的數(shù)據(jù),就必須發(fā)起請(qǐng)求,如果不做一些處理,就會(huì)受到瀏覽器同源策略的約束。后端可以收到請(qǐng)求并返回?cái)?shù)據(jù),但是前端無(wú)法收到數(shù)據(jù)。
為何瀏覽器會(huì)制定同源策略之所以有同源策略,其中一個(gè)重要原因就是對(duì)cookie的保護(hù)。cookie 中存著sessionID 。黑客一旦獲取了sessionID,并且在有效期內(nèi),就可以登錄。當(dāng)我們?cè)L問了一個(gè)惡意網(wǎng)站 如果沒有同源策略 那么這個(gè)網(wǎng)站就能通過js 訪問document.cookie 得到用戶關(guān)于的各個(gè)網(wǎng)站的sessionID 其中可能有銀行網(wǎng)站 等等。通過已經(jīng)建立好的session連接進(jìn)行攻擊,比如CSRF攻擊。
這里需要服務(wù)端配合再舉個(gè)例子,現(xiàn)在我扮演壞人 我通過一個(gè)iframe 加載某寶的登錄頁(yè)面 等傻傻的用戶登錄我的網(wǎng)站的時(shí)候 我就把這個(gè)頁(yè)面彈出 用戶一看 阿里唉大公司 肯定安全 就屁顛屁顛的輸入了密碼 注意 如果沒有同源策略 我這個(gè)惡意網(wǎng)站就能通過dom操作獲取到用戶輸入的值 從而控制該賬戶所以同源策略是絕對(duì)必要的.
還有需要注意的是同源策略無(wú)法完全防御CSRF。
跨域可以大概分為兩種目的
前后端分離時(shí),前端為了獲取后端數(shù)據(jù)而跨域
為不同域下的前端頁(yè)面通信而跨域
為前后端分離而跨域 Cross Origin Resource Share (CORS)CORS是一個(gè)跨域資源共享方案,為了解決跨域問題,通過增加一系列請(qǐng)求頭和響應(yīng)頭,規(guī)范安全地進(jìn)行跨站數(shù)據(jù)傳輸
請(qǐng)求頭主要包括請(qǐng)求頭 | 解釋 |
---|---|
Origin | Origin頭在跨域請(qǐng)求或預(yù)先請(qǐng)求中,標(biāo)明發(fā)起跨域請(qǐng)求的源域名。 |
Access-Control-Request-Method | Access-Control-Request-Method頭用于表明跨域請(qǐng)求使用的實(shí)際HTTP方法 |
Access-Control-Request-Headers | Access-Control-Request-Headers用于在預(yù)先請(qǐng)求時(shí),告知服務(wù)器要發(fā)起的跨域請(qǐng)求中會(huì)攜帶的請(qǐng)求頭信息 |
with-credentials | 跨域請(qǐng)求攜帶cookie |
響應(yīng)頭 | 解釋 |
---|---|
Access-Control-Allow-Origin | Access-Control-Allow-Origin頭中攜帶了服務(wù)器端驗(yàn)證后的允許的跨域請(qǐng)求域名,可以是一個(gè)具體的域名或是一個(gè)*(表示任意域名)。 |
Access-Control-Expose-Headers | Access-Control-Expose-Headers頭用于允許返回給跨域請(qǐng)求的響應(yīng)頭列表,在列表中的響應(yīng)頭的內(nèi)容,才可以被瀏覽器訪問。 |
Access-Control-Max-Age | Access-Control-Max-Age用于告知瀏覽器可以將預(yù)先檢查請(qǐng)求返回結(jié)果緩存的時(shí)間,在緩存有效期內(nèi),瀏覽器會(huì)使用緩存的預(yù)先檢查結(jié)果判斷是否發(fā)送跨域請(qǐng)求。 |
Access-Control-Allow-Methods | Access-Control-Allow-Methods用于告知瀏覽器可以在實(shí)際發(fā)送跨域請(qǐng)求時(shí),可以支持的請(qǐng)求方法,可以是一個(gè)具體的方法列表或是一個(gè)*(表示任意方法)。 |
客戶端只需按規(guī)范設(shè)置請(qǐng)求頭。
服務(wù)端按規(guī)范識(shí)別并返回對(duì)應(yīng)響應(yīng)頭,或者安裝相應(yīng)插件,修改相應(yīng)框架配置文件等。具體視服務(wù)端所用的語(yǔ)言和框架而定
SpringBoot 設(shè)置CORS例子一個(gè)spring boot項(xiàng)目中關(guān)于CORS配置的一段代碼
HttpServletResponse httpServletResponse = (HttpServletResponse) response; String temp = request.getHeader("Origin"); httpServletResponse.setHeader("Access-Control-Allow-Origin", temp); // 允許的訪問方法 httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH"); // Access-Control-Max-Age 用于 CORS 相關(guān)配置的緩存 httpServletResponse.setHeader("Access-Control-Max-Age", "3600"); httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,token"); httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");JSONP 跨域
jsonp的原理就是借助HTML中的