什么是跨域,為什么會有跨域問題的出現


一、什么是同源策略?

1、同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。
2、所謂同源是指"協議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
3、同源策略限制以下幾種行為:
(1)Cookie、LocalStorage 和 IndexDB 無法讀取
(2)DOM 和 Js對象無法獲得
(3)AJAX 請求不能發送

瀏覽器采用同源策略,禁止頁面加載或執行與自身來源不同的域的任何腳本。換句話說瀏覽器禁止的是來自不同源的"document"或腳本,對當前"document"讀取或設置某些屬性。

情景: 

比如一個惡意網站的頁面通過iframe嵌入了銀行的登錄頁面(二者不同源),如果沒有同源限制,惡意網頁上的javascript腳本就可以在用戶登錄銀行的時候獲取用戶名和密碼。

瀏覽器中有哪些不受同源限制呢?

<script>、<img>、<iframe>、<link>這些包含 src 屬性的標簽可以加載跨域資源。但瀏覽器限制了JavaScript的權限使其不能讀、寫加載的內容。

常見的解決方案分為三種,Nginx代理(前端實現),JSONP(前端實現),后台設置(后端實現)。

1.Nginx代理(前端實現):

案例說明:前端項目部署在8081端口,后端8081端口。

 

 

nginx監聽8081端口,將前端從nginx監聽的端口8081請求過來的請求,代理轉發到8080端口(8080為后端接口)


 

1、JSONP

前端實現:

$.ajax({
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 請求方式為jsonp
jsonpCallback: "onBack", // 自定義回調函數名
data: {}
});

后端實現(SpringBoot)

@ControllerAdvice(basePackages = "com.zkn.learnspringboot.web.controller")
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{

public JsonpAdvice() {

super("callback","jsonp");
}
}

(1)前端發起請求時候,會加一個參數表示回調的函數 比如 callback=callback124 (callback 參數名也是可以自定義的,和后端協商好就行)
         后端返回的數據 callback124({“uid”:1})
(2)參考:前端常見跨域解決方案(全)  https://segmentfault.com/a/1190000011145364 

(3)JSONP的缺點

         JSONP只支持 GET 請求。

(4)原理

         JSONP 是通過動態添加<script>標簽來調用服務器的腳本(<script>含有src屬性,src屬性沒有跨域限制);而 Ajax 是通過 XHR(XmlHttpRequest) 對象。

2、跨域技術-CORS (CrossOrigin Resources Sharing,跨源資源共享)

     CORS是什么?

    CORS,是 HTML5 的一項特性,它定義了一種瀏覽器和服務器交互的方式來確定是否允許跨域請求。

    相對於 JSONP 這種解決方案來說,使用CORS,不需要要求服務器以指定格式返回數據(包裝成JS腳本的格式:callback_func({ data }););CORS,只需要在服務器端做一些通用設置。

前端實現:

$.ajax({
type: "post",
url: 'http://192.168.45.152:8081/conference/user/bind',
async: false, // 使用同步方式
// 1 需要使用JSON.stringify 否則格式為 a=2&b=3&now=14...
// 2 需要強制類型轉換,否則格式為 {"a":"2","b":"3"}
data: JSON.stringify({ 
a: 1,
b: '2',
now: new Date().getTime() // 注意不要在此行增加逗號
}),
headers: {
'Authentication':'xxxxxx'
},
contentType: "text/plain",
dataType: "json",
success: function(data) {
console.log(data)
} // 注意不要在此行增加逗號
});

 


后端實現(SpringBoot):

@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
//設置允許跨域的路徑
registry.addMapping("/**")
//設置允許跨域請求的域名
.allowedOrigins("*")
//是否允許證書 不再默認開啟
.allowCredentials(true)
//設置允許的方法
.allowedMethods("GET", "POST")
//跨域允許時間
.maxAge(3600);

}
}

CORS與JSONP的使用目的相同,但是比JSONP更強大。

JSONP只支持GET請求,CORS支持所有類型的HTTP請求。JSONP的優勢在於支持老式瀏覽器,以及可以向不支持CORS的網站請求數據。

 

四、跨域會話保持

對於前端來說,seesion字段是存在cookie中的。在跨域過程中,Cookie是默認不發送的。就算后端返回set-Cookie字段,前端也不會保存Cookie,更不會在下一次訪問的時候發送到后端了。
因此只要前端可以把cookie發送到后端,后端就可以根據cookie拿到seeion字段進行會話驗證。
進過重新對CORS的學習,只要通過3步,就可以讓會話保持。

1、在ajax中設置,withCredentials: true。
默認情況下,跨源請求不提供憑據(cookie、HTTP認證及客戶端SSL證明等)。通過將withCredentials屬性設置為true,可以指定某個請求應該發送憑據。

$.ajax({
url: a_cross_domain_url,
xhrFields: {
withCredentials: true
}
});

第二第三步,就是上面的服務端CORS的跨域技術

服務端的 Access-Control-Allow-Credentials: true,代表服務器接受Cookie和HTTP認證信息。

 

參考資料:

(1)前后端分離-跨域會話如何保持?

https://www.jianshu.com/p/26f877d2b315?tdsourcetag=s_pcqq_aiomsg

(2)Session與Token認證機制 前后端分離下如何登錄

https://www.cnblogs.com/eret9616/p/9661314.html?tdsourcetag=s_pcqq_aiomsg

(3)理解Cookie和Session機制

https://www.cnblogs.com/andy-zhou/p/5360107.html

 

轉: https://blog.csdn.net/kevinxxw/article/details/90547184

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM