我們在做前後端數據交互或是做前後端分離項目時,經常會碰到請求跨域,什麼是跨域請求呢,這要先從同源策略說起,最初是由Netscape 公司將此策略引入瀏覽器。 同源策略是瀏覽器的一個安全功能,不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方資源,也是瀏覽器對javascript施加的安全限制,所以類似ab.com下的js腳本採用ajax讀取abc.com裡面的文件數據是會被拒絕的,因為域名不同。同源策略限制了腳本(js)跨網站發請求,可發請求但是拿不到響應。一個源要求:
協議(http/https)+IP(或域名)+端口都一致,就是同一個源。
但也有些不受同源策略限制,主要有 a標籤、img 標籤,重定向、form表單的提交,script、link,iframe標籤等不受同源策略的限制,可以引用其他站點內容。
跨域要解決不同源之間發起請求、請求數據、發送數據、通信等交互問題的問題。
解決方案:
- 修改瀏覽器的設置,解除同源策略限制。
我覺得此種方式只適合開發臨時調試等。例如chrome瀏覽器的跨域設置。在屬性頁面中的目標輸入框里加上 --disable-web-security 。此種方式限於版本號49之前,之後的步驟會多一些,版本號49之前設置如圖:
2.ajax 的jsonp方式處理跨域
JSONP 是 JSON with padding(填充式 JSON 或參數式 JSON)的簡寫。JSONP實現跨域請求的原理簡單的說,就是動態創建script標籤,然後利用script的src不受同源策略約束來跨域獲取數據。但是使用JSONP只支持GET,不支持POST請求。此種方式在開放API中起到非常重要的作用。
使用jQuery封裝的$.ajax中有一個dataType屬性,如果將該屬性設置成dataType:"jsonp",就能實現JSONP跨域了。
$.ajax({ async : true, url : "https://api.a.com/v1/book/search", type : "GET", dataType : "jsonp", // 返回的數據類型,設置為JSONP方式 jsonp : 'callback', //指定一個查詢參數名稱來覆蓋默認的 jsonp 回調參數名 callback jsonpCallback: 'handleResponse', //設置回調函數名 data : { q : "javascript", count : 1 }, success: function(response, status, xhr){ console.log('狀態為:' + status + ',狀態是:' + xhr.statusText); console.log(response); } });
3.使用反向代理功能解決跨域問題
使用nginx做請求轉發,配置:
修改:/usr/local/etc/nginx/vhosts/xx.com.conf
server { listen 80; server_name xx.com 12.12.12.12; location / { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' '*'; proxy_pass http://localhost:8088; # proxy_redirect off ; index index.php index.html index.htm; } }
4.使用nodejs中間件代理解決跨域問題
var express = require('express');
var proxy = require('http-proxy-middleware');var app = express();app.use('/', proxy({ target: 'http://www.a.com', changeOrigin: true }));app.listen(3000);5.使用CORS方式解決跨域問題
Cross-Origin Resource Sharing(CORS)跨域資源共享是一份瀏覽器技術的規範,是一個W3C標準,提供了 Web 服務從不同域傳來沙盒腳本的方法,以避開瀏覽器的同源策略。與 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。一些老舊瀏覽器如IE6,IE7,Opera min 不支持CORS.服務器端對於CORS的支持,是通過設置Access-Control-Allow-Origin來進行的。
如果使用springboot 框架,可配置
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter{
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
如果是springcloud 框架,可配置:
CORS 並不是為了解決服務端安全問題,而是為了解決如何跨域調用資源。至於如何設計出 安全的開放API,卻是另一個問題了,這裡提下一些思路:比如請求時間有效性 ,token驗證ip驗證和來源驗證等。