Ajax是會(huì)受到同源的影響的,當(dāng)我們要使用非同源的資源的時(shí)候,就會(huì)報(bào)錯(cuò),所以說Ajax只能獲取同源的資源。
但是有解決辦法讓Ajax獲取不同源的資源,需要遵循CORS機(jī)制。需要服務(wù)器給響應(yīng)當(dāng)中有一個(gè)“Access-Control-Allow-Origin”字段,如果響應(yīng)中沒有這個(gè)字段的話,就會(huì)報(bào)錯(cuò)。
1. 什么是CORS
cross-origin resource sharing(CORS)跨域資源共享,是一種使用額外HTTP首部實(shí)現(xiàn)跨域獲取資源權(quán)限的機(jī)制。
header(“Access-Control-Allow-Origin: *”); 這句話的意思是服務(wù)器允許哪個(gè)源向我這里獲取數(shù)據(jù),如果不設(shè)置的話,只能允許同源的來獲取數(shù)據(jù)。(這里的 * 表示的是允許所有的源都可以來我這里獲取數(shù)據(jù)。)
這里也可以設(shè)置固定的某一些域,比如:header(“Access-Control-Allow-Origin: http://localhost”);表示的是只能“http://localhost”下面的源能訪問,其他的源訪問的話就不允許了。
2. CORS分類
2.1 簡單請(qǐng)求
- 使用下列方法之一:
a. GET
b. POST
c. HEAD - content-Type值為下列之一:
a. text/plain
b. multipart/form-data
c. application/x-www-form-urlencoded等
除了正常發(fā)起請(qǐng)求外,若想實(shí)現(xiàn)cors跨域,還需要服務(wù)器配置正確的響應(yīng)首部。否則無法獲取
access-contral-allow-origin: *(http://localhost) 訪問控制允許源。
注意:需同時(shí)滿足上面兩個(gè)條件才是一個(gè)簡單請(qǐng)求。
2.2 預(yù)檢請(qǐng)求
“需預(yù)檢的請(qǐng)求”要求必須首先使用OPTIONS(查詢支持的方法
)方法發(fā)起一個(gè)預(yù)檢請(qǐng)求到服務(wù)器,以獲知服務(wù)器是否允許該實(shí)際請(qǐng)求(如使用DELETE請(qǐng)求,那么它首先會(huì)發(fā)起一個(gè)請(qǐng)求(其實(shí)就是預(yù)檢請(qǐng)求),先向服務(wù)器中去問一下,你是否允許DELETE請(qǐng)求,如果允許的話那么我再發(fā)送一個(gè)請(qǐng)求,才能正式的去DELETE)。
預(yù)檢請(qǐng)求是需要發(fā)送兩次請(qǐng)求的,一次是*OPTIONS請(qǐng)求,還有一次才是正式的我們想要發(fā)送的請(qǐng)求。
“預(yù)檢請(qǐng)求“的使用,可以避免跨域請(qǐng)求對(duì)服務(wù)器的用戶數(shù)據(jù)產(chǎn)生未預(yù)期的影響。
當(dāng)請(qǐng)求滿足下述任一條件時(shí),即應(yīng)首先發(fā)送預(yù)檢請(qǐng)求:
1. 使用非GET POST HEAD方法
2. content-Type值不為下列之一:
a. text/plain
b. multipart/form-data
c. application/x-www-form-urlencoded
3. 人為設(shè)置了 CORS 安全的首部字段集合之外的首部字段,如人為的寫一個(gè)CORS安全的首部字段集合(xml.setRequestHeader(‘X-user’,’daipi173′);):https://fetch.spec.whatwg.org/#cors-safelisted-request-header
例如:發(fā)起POST請(qǐng)求,人為設(shè)置了X-user:daipi173字段,則需要預(yù)檢請(qǐng)求。此時(shí)就需要服務(wù)器設(shè)置正確的字段:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Request-Methods: POST,GET,PUT,DELETE,OPTIONS"); //實(shí)際請(qǐng)求所允許使用的HTTP方法
header("Access-Control-Allow-Headers: X-user, content-type"); //請(qǐng)求中允許攜帶的首部字段
header("Access-Control-Max-Age: 86400"); //請(qǐng)求的結(jié)果能夠被緩存,可以不用設(shè)置,不設(shè)置的話就是一個(gè)臨時(shí)緩存
注意:如果當(dāng)你再一次發(fā)送的話,它就不會(huì)幫你預(yù)檢了。因?yàn)榘l(fā)送的請(qǐng)求已經(jīng)預(yù)檢過了,并且是符合的,那么你發(fā)送請(qǐng)求的時(shí)候它就不幫你再預(yù)檢了。
CORS跨域,前端需要做的事情其實(shí)是很少的,更多的是后端與我們前端來進(jìn)行一個(gè)配合。