前端處理
原生 js 中 ajax
const url = `接口地址`; let xml = new XMLHttpRequest(); xhr.withCredentials = true; //一個布爾值,用來指定跨域 Access-Control 請求是否應帶有授權信息,如 cookie 或授權 header 頭。 xml.open('POST', url) //設置請求方式及接口地址 xml.setRequestHeader("token",window.localStorage.getItem('token')); //設置請求頭,按需使用 xml.send(); xml.onreadystatechange = (e) => { //服務端響應後 if (xml.readyState == 4) { //判斷客戶端是否可以使用 if(xml.status == 200){ //表示成功處理請求 alert("請求成功"); } } }
jquery 中 ajax
$.ajax({ url: "http://localhost:8080/orders", type: "GET", // 默認情況下,標準的跨域請求是不會發送cookie的 xhrFields: { withCredentials: true }, // 如果 攜帶不過去去 withCredentials:true,可以使用下面的方法 /* beforeSend: function (xhr) { xhr.withCredentials = true }, */ crossDomain: true, //false表示同一域請求,true表示跨域請求,攜帶跨域的額外信息,不包括cookie。 success: function (data) { render(data); } });
注意:支持withCredentials屬性的瀏覽器有Firefox 3.5+、Safari 4+和Chrome。IE10及更早版本都不支持。
在jQuery1.5中,withCredentials這個屬性不在原生的xhr中,所以這個請求會被忽略到。若要測試這個例子,需要使用jQuery1.5.1。
// 單獨設置 axios.defaults.withCredentials = true // 或者在 axios 配置項中設置,表示跨域請求時是否需要使用憑證 withCredentials: true,
vue 中設置代理
後端配置
// 允許的頭部攜帶的信息 X-Requested-With 區分ajax 請求還是普通方法請求 header('Access-Control-Allow-Headers:X-Requested-With,Content-Type,XX-Device-Type,XX-Token,XX-Api-Version,XX-Wxapp-AppId,Authorization,Cookie'); // 允許請求的方法 header('Access-Control-Allow-Methods:GET,POST,PATCH,PUT,DELETE,OPTIONS'); if(strtoupper($request->method())== 'OPTIONS'){ // 跨域問題 允許訪問的域名,如果前端配置了這個withCredentials=true,後段設置Access-Control-Allow-Origin不能爲 " * ",必須是你的源地址 header('Access-Control-Allow-Origin:源地址'); // 對請求的響應允許暴露前端的js,服務端使用session 存儲,session 是依賴於 cookie,所以前端必須允許攜帶 cookie header('Access-Control-Allow-Credentials:true'); exit; }
前端 ajax 會發送2次請求,是因爲使用了帶預檢(Preflighted)的跨域請求。該請求會在發送真實的請求之前發送一個類型爲OPTIONS的預檢請求。預檢請求會檢測服務器是否支持我們的真實請求所需要的跨域資源,唯有資源滿足條件纔會發送真實的請求。比如我們在請求頭部增加了authorization項,那麼在服務器響應頭中需要放入Access-Control-Allow-Headers,並且其值中必須要包含authorization,否則OPTIONS預檢會失敗,從而導致不會發送真實的請求。當前使用的是 PHP 語言,如果請求方法是 OPTIONS,直接返回不處理。
服務器配置
如果前端使用了 Authorization ,服務端(apache)需要配置, 在根目錄創建 .htaccess 文件
// 第一種方法 Authorization Headers RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] // 第二種方法 <IfModule mod_rewrite.c> SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0 </IfModule>
nginx 服務器反向代理
server { # nginx監聽所有 test.com:9000 端口收到的請求 listen 9000; server_name test.com; # test.com:9000 會被轉發到 192.168.25.20:9000 location / { proxy_pass http://192.168.25.20:9000; } # test.com:9000/api/ 會被轉發到 "192.168.25.20:9000/api/" location /api/ { proxy_pass http://192.168.25.20:9000; } }