溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

CORS機(jī)制及其風(fēng)險(xiǎn)

發(fā)布時(shí)間:2020-06-14 07:15:06 來源:網(wǎng)絡(luò) 閱讀:12394 作者:cnn237111 欄目:web開發(fā)

根據(jù)同源策略,瀏覽器默認(rèn)是不允許XMLHttpRequest對(duì)象問非同一站點(diǎn)下的資源的,即用ajax方式訪問非同一域名下的資源會(huì)出錯(cuò)。比如當(dāng)google要通過ajax去訪問百度的數(shù)據(jù),是不行的。

所謂同源,是要求協(xié)議,域名,端口都相同。

比如 http://www.aaa.com 和下列URL相比,都不屬于同源。

https://www.aaa.com

http://www.aaa.com:8080

http://aaa.com

但下面這種屬于同源:

http://username:password@www.aaa.com

禁用跨域訪問資源是為了安全,但會(huì)犧牲便利性。因此就出現(xiàn)了好幾種跨域訪問資源的方法。其中一種是稱之為CORS的技術(shù)(Cross-origin resource sharing)。

CORS的概念

所謂CORS(Cross-origin resource sharing ),是指通過XMLHttpRequest的ajax方式訪問其他域名下資源,而不是在A域名的頁面上點(diǎn)擊打開一個(gè)B域名的頁面。引入不同域上的js腳本文件也是沒用問題的。出于安全考慮,跨域請(qǐng)求不能訪問document.cookie對(duì)象。

CORS技術(shù)允許跨域訪問多種資源,比如javascript,字體文件等,這種技術(shù)對(duì)XMLHttpRequest做了升級(jí),使之可以進(jìn)行跨域訪問。但不是所有的瀏覽器都支持CORS技術(shù)。Firefox和Chrome等瀏覽器支持的比較好,稍微新一點(diǎn)的版本都支持。IE比較搓,IE10才真正支持這個(gè)機(jī)制,IE10以下需要用XDomainRequest這個(gè)對(duì)象,這是IE特有的。

當(dāng)然不是說瀏覽器支持了就立刻可以跨域訪問了,CORS技術(shù)中最重要的關(guān)鍵點(diǎn)是響應(yīng)頭里的Access-Control-Allow-Origin這個(gè)Header。 此Header是W3C標(biāo)準(zhǔn)定義的用來檢查是可否接受跨域請(qǐng)求的一個(gè)標(biāo)識(shí)。實(shí)現(xiàn)過程大致如下:A域名中發(fā)起跨域請(qǐng)求到B域名,B域名如果發(fā)送響應(yīng)頭Access-Control-Allow-Origin: A域名,那么A域名的這次跨域請(qǐng)求就能成功。反之則不成功。這里有一個(gè)稱之為Preflighted requests 的步驟,這一步驟中,瀏覽器發(fā)起一個(gè)OPTIONS請(qǐng)求,去服務(wù)器驗(yàn)證是否支持跨域訪問。(

用chrome去查看這個(gè)option請(qǐng)求始終看不到,只有當(dāng)跨域訪問請(qǐng)求非正常(比如本人筆誤,將請(qǐng)求type的get誤寫成了gey)的情況下,才會(huì)看到有個(gè)OPTIONS請(qǐng)求,如圖:CORS機(jī)制及其風(fēng)險(xiǎn)

非常奇怪,不知道為何。

CORS的實(shí)現(xiàn)

舉個(gè)例子。

有2個(gè)站點(diǎn),分別綁定了www.myhost1.com和www.myhost2.com:8001這個(gè)兩個(gè)域名。

假設(shè)www.myhost2.com:8001下的a.html文件,需要訪問www.myhost1.com域名下的b.aspx文件,代碼如下。

a文件代碼如下,點(diǎn)擊按鈕就會(huì)去跨域訪問b頁面:

<!DOCTYPE html>  
<html lang="en" xmlns="
http://www.w3.org/1999/xhtml
">    
<head>    
<meta charset="utf-8" />    
<title>Apage</title>    
<script type="text/javascript" src="
http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js
"></script>    
<script>    
$(function () {    
var options = {    
type: 'get',    
url: "
http://www.myhost1.com/mysite/cors/b.aspx
",    
success: function (result) {    
alert(result);    
}    
};    
$("#btn1").click(function () {    
$.ajax(options);    
});    
});    
</script>    
</head>    
<body>    
<input type="button" id="btn1" value="load page b" />    
</body>    
</html>

b文件為一個(gè)aspx文件,代碼非常簡(jiǎn)單,顯示時(shí)間

<%@ Page Language="C#" %>
<%=DateTime.Now%>

A文件的地址為http://www.myhost2.com:8001/a.html

A文件的請(qǐng)求是按照get方式讀取的,當(dāng)A文件點(diǎn)擊按鈕,會(huì)彈出B文件的內(nèi)容。由于同源策略,會(huì)看到如下錯(cuò)誤:

CORS機(jī)制及其風(fēng)險(xiǎn)

為了避免這個(gè)錯(cuò)誤,在www.myhost1.com主機(jī)的Http響應(yīng)標(biāo)頭里加上Access-Control-Allow-Origin:http://www.myhost2.com:8001,注意不要打上最后一個(gè)斜杠/,意思是允許http://www.myhost2.com:8001這個(gè)域名中的XMLHttpRequest對(duì)象跨域訪問www.myhost1.com主機(jī)下的資源。

CORS機(jī)制及其風(fēng)險(xiǎn)

還有一種方法是修改web.config,Access-Control-Allow-Origin的值可以是通配符*,比如如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
    <httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Origin" value="*" />
     </customHeaders>
   </httpProtocol>
  </system.webServer>
</configuration>

或者通過代碼添加響應(yīng)標(biāo)頭來實(shí)現(xiàn)。

<%@ Page Language="C#" %>     
<%
Response.AppendHeader("Access-Control-Allow-Origin", "http://www.myhost2.com:8001");     %>
<%=DateTime.Now%>

當(dāng)瀏覽器通過ajax請(qǐng)求訪問其他域名下的資源時(shí),如果那個(gè)資源的響應(yīng)頭中包含了Access-Control-Allow-Origin,則可以請(qǐng)求成功,否則就會(huì)失敗,是否設(shè)置了響應(yīng)頭,可以在firebug等調(diào)試工具內(nèi)看到。

無響應(yīng)頭

CORS機(jī)制及其風(fēng)險(xiǎn)

有響應(yīng)頭

CORS機(jī)制及其風(fēng)險(xiǎn)

跨域訪問的風(fēng)險(xiǎn)

默認(rèn)情況下,CORS機(jī)制不讀取cookie值,即跨域訪問時(shí)沒有帶上cookie,當(dāng)需要跨域訪問帶cookie時(shí),需要設(shè)置另一個(gè)文件頭,Access-Control-Allow-Credentials,值為true。該選項(xiàng)設(shè)定了是否允許跨域請(qǐng)求帶cookie。當(dāng)設(shè)定為true后,對(duì)于XMLHttpRequest還需要設(shè)定withCredentials為true,在Jquery中為xhrFields: {withCredentials: true}

一旦允許了帶cookie的跨域訪問,那么遭到CSRF***的概率大大的增加了,比如之前的假設(shè)a.html頁面內(nèi)有一段惡意的js,它每隔1分鐘去跨域請(qǐng)求用戶b頁面,并將請(qǐng)求后的數(shù)據(jù)偷偷的存入自己的數(shù)據(jù)庫內(nèi)。假設(shè)b頁面需在要用戶登錄的情況下,可以請(qǐng)求到很多機(jī)密數(shù)據(jù),比如信用卡號(hào)等,那當(dāng)用戶打開a頁面后,在非授意的情況下,獲取到b面值的內(nèi)容,引發(fā)泄密。

對(duì)之前的演示代碼做小的修改:

a頁面代碼:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta 
charset="utf-8" />
<title>Apage</title>
<script 
type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
<script>
$(function 
() {
var options = {
type: 'get',
xhrFields: {withCredentials: true},
url: "http://www.myhost1.com/mysite/cors/b.aspx",
success: 
function (result) {
alert(result);
}
};
$("#btn1").click(function () 
{
$.ajax(options);
});
});
</script>
</head>
<body>
<input 
type="button" id="btn1" value="load page b" 
/>
</body>
</html>

b.aspx頁面代碼如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="b.aspx.cs" %>  
<%  
    Response.AppendHeader("Access-Control-Allow-Origin", "
http://www.myhost2.com:8001
");  
    Response.AppendHeader("Access-Control-Allow-Credentials", "true");  
    if (Session["islog"] != null)  
    {  
        if (Session["islog"] == "1")  
        {  
            Response.Write("已登錄,顯示機(jī)密信息 ");  
        }  
    }  
    else  
    {  
        Response.Write("未登錄");  
    }  
    if (Request["login"] == "true")  
    {  
        Session["islog"] = "1";  
        Session.Timeout = 1;  
        Response.Write("Login in OK");  
    }  
%>  
<%=DateTime.Now%>

假設(shè)b頁面的用戶登錄了一下,種植了一個(gè)session,那么就會(huì)有一個(gè)sessionid被存儲(chǔ)到用戶的cookie中去,此時(shí),a頁面點(diǎn)擊按鈕后,會(huì)獲取b頁面顯示的內(nèi)容,根據(jù)***的行為,可以有更大的破壞力。

演示圖:當(dāng)b頁面未登錄時(shí),顯示未登錄。請(qǐng)求中不帶cookie。

CORS機(jī)制及其風(fēng)險(xiǎn)

但是當(dāng)b頁面已經(jīng)登錄,則在a頁面中的跨域請(qǐng)求中,帶有cookie,會(huì)顯示已登錄的頁面。

CORS機(jī)制及其風(fēng)險(xiǎn)

CORS機(jī)制及其風(fēng)險(xiǎn)

參考資料:

http://drops.wooyun.org/tips/188

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing  
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS  
https://dev.opera.com/articles/dom-access-control-using-cors/  
http://blog.darkthread.net/post-2014-09-29-cors-options-preflight-and-iis.aspx

http://www.cnblogs.com/idche/p/3190926.html

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI