在控制層加了以下代碼:php
header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN'] ); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept');
打開chrome的network裏的response,沒有這幾個值~html
可是一樣的代碼我在本地另外一個項目裏是OK的,項目環境是Nginx作了層代理,實際用的是PHP當Apache模塊的方式,就開始懷疑:前端
用xdebug跟了下,沒看到框架裏有任何限制不能更改headerweb
看到response每次返回的都同樣,覺得是運維控制了返回的選項,不能隨意添加,和運維同事溝通了下,發現確實是不能隨意添加header頭,竊喜覺得找到了緣由。然而另外一個同事說加的跨域容許是OK的;Nginx的conf里加的proxy 也是把Apache返回的header都返回了,排除ajax
從新思考,跨域問題是瀏覽器控制的,只要HTTP協議裏返回的access容許就能夠了。chrome
使用header_list()
方法打印了下發送的header列表,發現本身寫的那幾個沒返回。數據庫
換種思路,把這幾行加到其餘文件,發現能夠,而後對比倆文件有啥區別,最後最後的緣由是<?php
這個標識是從第2行開始寫的,即在header方法以前有了輸出。json
參考:跨域
瀏覽器安全的基石是"同源政策",若是非同源,共有3種行爲受到限制
這裏主要討論下ajax的跨域解決方法,
全稱:json for padding 本質是用<script>
標籤能夠跨域訪問的性質,動態建立一個script,而後回調js數據腳本,請求類型是js而非xhr.普通接口返回的是數據對象,而jsonp是js數據腳本
CORS是一個W3c標準,全稱是「跨域資源共享」(cross-origin resource sharing),容許瀏覽器向跨源服務器,發出XMLHttpRequest請求。
須要瀏覽器和服務器同時支持。目前全部瀏覽器都支持該功能,整個cors通訊過程不須要用戶參與。
瀏覽器將cors請求分爲兩種:簡單請求和非簡單請求
只要同時知足如下兩個條件,就屬於簡單請求:
(1) 請求方法是如下三種方法之一:
HEAD GET POST
(2)HTTP的頭信息不超出如下幾種字段:
Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
不然屬於非簡單請求。
瀏覽器在頭信息中增長一個origin
字段,用來講明本次請求來自哪一個源(協議+域名+端口)。服務器根據這個值決定是否贊成此次請求。
若是服務器沒有返回access這樣的頭部信息,即服務器沒支持的話,前端的console裏會顯示access to xmlHttpRequest ...has been blocked by CORS policy...
若是origin指定的域名在許可範圍內,服務器返回的響應會多出幾個頭信息字段:
Access-Control-Allow-Origin: xxxx Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: xxx
Access-Control-Allow-Origin:
是必須的,值要麼是請求時origin字段的值,要麼是*表示接受任意域名的請求。
Access-Control-Allow-Credentials
可選,布爾值,表示是否容許發送cookie,不一樣源時請求中不會帶cookie,設爲true表示服務器許可cookie能夠包含在請求中,
XMLHttpRequest.withCredentials
屬性是一個boolean類型,表示是否該使用cookie,authorization header(頭部受權)或者TLS客戶端證書這一類資格證書來建立一個跨站點訪問控制請求。
參考:
xmlHttpRequest.withCredentials
Access-Control-Expose-Headers
可選,cors請求時,xmlHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。若是想拿到其餘字段,就必須在Access-Control-Expose-Headers裏面指定。
若是要帶上cookie,後臺的origin就不能設爲*,且須要前端設置以下:
var xhr = new XMLHttpRequest(); xhr.withCredentials = true;
是對服務器有特殊請求的:如請求方法是put或delete,或者content-type字段的類型是application/json.
非簡單請求會在正式通訊以前,增長HTTP查詢請求,稱爲預檢請求。瀏覽器先詢問服務器,當前網頁所在的域名是否在服務器的許可名單中,以及可使用那些HTTP動詞和頭信息字段。只有獲得確定答覆,瀏覽器纔會發出正式的XMLHttpRequest請求,不然就報錯。
預檢請求
1)請求:
預檢請求用的方法是option
,表示這個請求時用來詢問的。頭信息裏關鍵字段是origin表示請求來自哪一個源。
2)迴應:
服務器收到預檢請求後,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段之後,確認容許跨源請求,就能夠作出迴應。
服務器返回的Access-Control-Max-Age
該字段可選,用來指定本次預檢請求的有效期,單位爲秒。上面結果中,有效期是20天(1728000秒),即容許緩存該條迴應1728000秒(即20天),在此期間,不用發出另外一條預檢請求
一旦服務器經過了預檢請求,之後每次瀏覽器正常的cors請求都和簡單請求同樣。