業務場景:
前后端分離需要對接數據接口。
接口測試是在postman做的,今天才開始和前端對接,由於這是我第一次做后端接口開發(第一次嘛,問題比較多)所以在此記錄分享我的踩坑之旅,以便能更好的理解,應用。
問題:
前端ajax請求后端接口出現跨域問題,如下圖。
翻譯:因為響應頭沒有"Access-Control-Allow-Origin",所以接口拒絕把數據返回給前端。
什么是Access-Control-Allow-Origin?
Access-Control-Allow-Origin是HTML5中定義的一種解決資源跨域的策略。
瀏覽器只允許請求當前域的資源,而對其他域的資源表示不信任。那怎么才算跨域呢?
- 請求協議
http,https的不同 - 域
domain的不同 - 端口
port的不同
其實說簡單點,跨域,指的就是瀏覽器不能執行其他網站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器施加的安全限制。
同源是指:協議相同,域名相同,端口相同。三者同時成立才能叫同源。
瀏覽器的同源策略從它誕生的那一刻就出現了,具體是指從域名A下的一個頁面(一般是通過ajax請求)獲取域名B下的一個資源,是不被瀏覽器允許的。
跨域資源共享(CORS)是瀏覽器提供的一種跨域協商機制,讓前后端協商是否可以發出跨域請求。 CORS添加了若干Access-controll-request-xxx 的頭,給客戶端聲明自己的源、要使用的頭部、用使用的請求方法;添加了若干Access-Controll-Allow-xxx的頭,給服務端聲明自己支持跨域的源、頭部和方法。
| URL | 說明 | 是否允許通信 |
|---|---|---|
| http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 | 允許 |
| http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不同文件夾 | 允許 |
| http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不同端口 | 不允許 |
| http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不同協議 | 不允許 |
| http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名對應ip | 不允許 |
| http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不同 | 不允許 |
| http://www.a.com/a.js http://a.com/b.js |
同一域名,不同二級域名(同上) | 不允許(cookie這種情況下也不允許訪問) |
| http://www.cnblogs.com/a.js http://www.a.com/b.js |
不同域名 | 不允許 |
兩種解決方案(從后端開始解決)
一、
1、后端返回Jsonp格式的數據,在Json格式的基礎上包上一層:handleCallback():
handleCallback({"status": true, "code": "200"})
==>
response.getWriter().write("handleCallback({\"status\": false, \"code\": \"500\"})");
2、前端ajax接收返回:
var userName=$("#userName").val(); var str_data={"UserName":userName}; $.ajax({ type: 'get', async : false, dataType: 'jsonp', //設置返回的類型時Jsonp類型 url: "http://localhost:8078/springBoot/User", jsonpCallback: "handleCallback", //關鍵:回調函數名,與后端一致 data:str_data, success: function(result){ console.log(result.code); }, error:function(result){ console.log("error"); } });
二、
1、后端直接設置Reponse允許跨域訪問
public void UploadUserAvatars(HttpServletRequest request,HttpServletResponse response) throws Exception{ // 指定允許其他域名訪問 response.addHeader("Access-Control-Allow-Origin","*"); // 響應類型 response.addHeader("Access-Control-Allow-Methods","POST"); // 響應頭設置 response.addHeader("Access-Control-Allow-Headers","x-requested-with,content-type"); //響應內容支持中文 response.setContentType("text/html;charset=utf-8"); }
