開發(fā)環(huán)境
前端VUE運(yùn)行在本地:http://localhost:8088
后端API運(yùn)行地址為http://www.imagemix.com
現(xiàn)在要通過axios調(diào)用后端接口,域名不同,瀏覽器依據(jù)同源策略,出現(xiàn)跨域問題.
原理
當(dāng)我們在代碼中寫的 (get,post)請(qǐng)求跨域時(shí), 瀏覽器在發(fā)出真正的請(qǐng)求前, 會(huì)自動(dòng)的向服務(wù)端發(fā)出一個(gè)OPTIONS
預(yù)檢請(qǐng)求, 然后瀏覽器通過分析服務(wù)端對(duì)OPTIONS
請(qǐng)求的響應(yīng)頭,來判斷服務(wù)端是否支持跨域.
完整步驟
-
瀏覽器發(fā)出
OPTIONS
請(qǐng)求
跨域請(qǐng)求 -
服務(wù)端收到請(qǐng)求,并做出響應(yīng)
服務(wù)端返回的響應(yīng) -
瀏覽器分析服務(wù)端的響應(yīng)信息,判斷是否支持跨域.
這次OPTIONS
請(qǐng)求服務(wù)端返回信息中沒有Access-Control-Allow-Origin
字段,瀏覽器判定服務(wù)端不支持跨域, 于是后續(xù)請(qǐng)求不會(huì)執(zhí)行
瀏覽器檢測結(jié)果
解決方法
如果服務(wù)端支持跨域, 那么服務(wù)端應(yīng)該正確響應(yīng)這個(gè)OPTIONS
請(qǐng)求,只要在返回的消息頭中加上對(duì)應(yīng)字段就行了
#在項(xiàng)目的入口文件里
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '*';
header('Access-Control-Allow-Origin:' . $origin);
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers:Origin,Token, No-Cache, uniqid, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With');
header('Access-Control-Expose-Headers:uniqid');
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS'){
exit();
}
其他說明
Access-Control-Allow-Origin: *
表示允許哪個(gè)域名跨域訪問Access-Control-Allow-Headers:
允許瀏覽器跨域時(shí)攜帶的自定義頭信息.
vue需要攜帶token,uniqid字段發(fā)送請(qǐng)求到服務(wù)器,在預(yù)檢請(qǐng)求中需要告訴瀏覽器支持的字段,否則前端會(huì)報(bào)錯(cuò)前后分離,導(dǎo)致生成的驗(yàn)證碼無法通過cookie驗(yàn)證, 于是我在返回驗(yàn)證碼圖片的同時(shí)返回了一個(gè)自定義header表示驗(yàn)證碼的唯一ID
uniqid = df2341f55fzz3vbd
, vue中需要記錄這個(gè)值, 提交表單時(shí)再傳上來.
需要加上header('Access-Control-Expose-Headers:uniqid');
vue才能取出這個(gè)自定義uniqid
var uniqid = response.headers.uniqid
另外記錄axios攜帶header的方式
get請(qǐng)求
axios
.get(
process.env.BASE_API+'/index.php/Home/Index/Code',
{
responseType: 'arraybuffer',
headers:{
uniqid:_that.formData.headers.uniqid
}
})
.then(function(response){
console.log(response)
var contentType = response.headers['content-type']
var uniqid = response.headers.uniqid
sessionStorage.setItem('uniqid',uniqid)
console.log(uniqid)
var blob = new Blob([response.data],{type:contentType})
_that.formData.verify = URL.createObjectURL(blob)
})
},