第72篇 跨域的簡單介紹

似梦亦非梦發表於2024-12-07

1.跨域的相關概念

1.1 什麼是跨域

同源策略是由 Netscape 提出的著名安全策略,是瀏覽器最核心、基本的安全功能,它限制了一個源(origin)中載入文字或者指令碼與來自其他源(origin)中資源的互動方式,所謂的同源就是指協議、域名、埠相同。
當瀏覽器執行一個指令碼時會檢查是否同源,只有同源的指令碼才會執行,如果不同源即為跨域。

域名組成:
image

1.2 為什麼會出現跨域

瀏覽器的同源策略,出於防範跨站指令碼的攻擊,禁止客戶端指令碼(如 JavaScript)對不同域的服務進行跨站呼叫(通常指使用 XMLHttpRequest 請求)。

1.3 瀏覽器的同源策略:Same-Origin Policy

  • 沒有同源策略的危害
    防止惡行請求
    案例講解:
    假設有一個駭客叫做小黑,他從網上抓取了一堆美女圖做了一個網站,每日訪問量爆表。
    為了維護網站執行,小黑掛了一張收款碼,覺得網站不錯的可以適當資助一點,可是無奈伸手黨太多,小黑的網站入不敷出。
    於是他非常生氣的在網頁中寫了一段js程式碼,使用ajax向淘寶發起登陸請求,因為很多數人都訪問過淘寶,所以電腦中存有淘寶的cookie,不需要輸入賬號密碼直接就自動登入了,然後小黑在ajax回撥函式中解析了淘寶返回的資料,得到了很多人的隱私資訊,轉手一賣,小黑的網站終於盈利了。
    如果跨域也可以傳送AJAX請求的話,小黑就真的獲取到了使用者的隱私併成功獲利了!!!

1.4 跨域有哪些限制

  • Cookie、LocalStorage 和 IndexDB 無法讀取。
  • DOM 無法獲得。:釣魚網站
  • AJAX 請求不能傳送。

1.5 Ajax請求步驟:

(1)建立XMLHttpRequest 物件。
(2)使用open方法設定請求的引數。open(method, url, 是否非同步)。
(3)傳送請求。
(4)註冊事件。 註冊onreadystatechange事件,狀態改變時就會呼叫。
(5)獲取返回的資料,更新UI。

2.JSONP(JSON with Padding)

2.1 概念

原理就是利用了 script 標籤不受同源策略的限制,在頁面中動態插入了 script,script 標籤的 src 屬性就是後端 api 介面的地址,並且以 get 的方式將前端回撥處理函式名稱告訴後端,後端在響應請求時會將回撥返還,並且將資料以引數的形式傳遞回去。

2.2 核心程式碼

前端:

	var script = document.createElement('script');
	script.src = 'http://127.0.0.1:2333/jsonpHandler?callback=_callback';
	document.body.appendChild(script);   

	var _callback = function(obj) {
	   for(key in obj) {
		 console.log('key: ' + key +' value: ' + obj[key]);
		}
	}

後端:

[HttpGet]
		[Route("jsonpForVue")]
		public void GetjsonpForVue(string callback)
		{

			TokenModelJwt tokenModelJwt=new TokenModelJwt(){
				Role="admin",
				Uid=1,
				Work="dsdf"
			};
			//string call = "({" + response + "})";
			string response = string.Format("\"name\":\"{0}\"", "zhagnsan");
			var modlestr = JsonConvert.SerializeObject(tokenModelJwt);
			string call = callback + "(" + modlestr + ")";
			Response.WriteAsync(call);
		}

2.3 優劣

劣:

  • 這種方式只能發生get請求;
  • 確定jsonp的請求是否失敗並不容易,大多數框架的實現都是結合超時時間來判定;
  • 不太安全,可能也會受到攻擊;

優:

  • 很簡單
  • 老式瀏覽器全部支援,伺服器改造非常小

3 Proxy代理

3.1 概念

  • vue-cli的proxyTable用的是http-proxy-middleware中介軟體
  • create-react-app用的是webpack-dev-server內部也是用的http-proxy-middleware
  • http-proxy-middleware內部用的http-proxy

跨域是瀏覽器禁止的,服務端並不禁止跨域

image

所以瀏覽器可以發給自己的服務端然後,由自己的服務端再轉發給要跨域的服務端,做一層代理。

3.2 核心程式碼

前端:

proxy: {
	  // 配置多個代理
	  "/api": {
		target: "http://localhost:5000",//這裡改成你自己的後端api埠地址,記得每次修改,都需要重新build
		//target: "http://localhost:58427",
		//target: "http://api.douban.com",
		ws: true,
		changeOrigin: true,
		pathRewrite: {
		  // 路徑重寫,
		  "^/apb": "" // 替換target中的請求地址
		}
	  }

image

3.3 優劣

缺點:不能用在生產環境,只能在開發環境;
優點:dev環境配置很簡單,支援多個域名;

4 CORS,全稱:Cross-Origin Resource Sharing(跨域資源共享)

4.1 概念

CORS是一種允許當前域(origin)的資源被其他域(origin)的指令碼請求訪問的機制。

當使用 XMLHttpRequest 傳送請求時,瀏覽器如果發現違反了同源策略就會自動加上一個請求頭 origin,後端在接受到請求後確定響應後會在 Response Headers 中加入一個屬性 Access-Control-Allow-Origin,值就是發起請求的源地址(http://127.0.0.1:8888),瀏覽器得到響應會進行判斷 Access-Control-Allow-Origin 的值是否和當前的地址相同,只有匹配成功後才進行響應處理。

簡單請求

  • GET
  • HEAD
  • POST
  • 條件 2:Content-Type 的值僅限於下列三者之一:
  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

複雜請求

4.2 核心程式碼

後端配置

4.3 優劣

缺點:

  • 部分老的瀏覽器不支援

優點:

  • 支援所有 Http 謂詞請求
  • 不用注意介面規則
  • 可用在生產環境

5 Nginx

概念:nginx解決跨域 是利用其反向代理的能力

5.1 跨域原理

Brower =》 host =》 nginx =》 目標地址伺服器資料 =》 nginx =》 Brower
也就是說,nginx並不是透過監聽brower的請求。而是作為一個伺服器,接收外部對本機的請求。所以是先透過host,讓請求指向本機,才會經過nginx。才能進行轉發。

  • 首先,直接在瀏覽器位址列中,輸入某介面地址。是不會產生跨域問題的。
  • 只有當在某域名的頁面中,由該頁面發起的介面請求。才可能會跨域。
  • nginx就類似於這個瀏覽器位址列,它接收到外部對它的請求( 注意,nginx只會接收別人對它的請求,而不會攔截瀏覽器的請求 ),再類似瀏覽器位址列一樣去請求某個介面。最後將請求到的內容返回回去

5.2 核心程式碼

server {
		listen       1005;
		server_name  localhost;
		location / {
			root   nuxt\Blog.Admin\dist;
			index  index.html index.htm;
		}
		location /api {
			rewrite  ^.+apb/?(.*)$ /$1 break;
			   include  uwsgi_params;
			proxy_pass   http://localhost:1004; #// 這是 netcore 埠
		}
		error_page  404              /404.html;
		error_page   500 502 503 504  /50x.html;
		location = /50x.html {
			root   html;
		}
	}

5.3 優劣

缺點:

  • 移植靈活性 低、每套環境配置可能均不相同

優點:

  • 對獨立性強的小專案,使用nginx則可以降低你的開發成本,快速發開快速上線

6 Socket

WebSocket是一種通訊協議,使用ws://(非加密)和wss://(加密)作為協議字首。該協議不實行同源政策,只要伺服器支援,就可以透過它進行跨源通訊。

核心程式碼:

var ws = new WebSocket('wss://echo.websocket.org'); //建立WebSocket的物件。引數可以是 ws 或 wss,後者表示加密。

	//把請求發出去
	ws.onopen = function (evt) {
		console.log('Connection open ...');
		ws.send('Hello WebSockets!');
	};


	//對方發訊息過來時,我接收
	ws.onmessage = function (evt) {
		console.log('Received Message: ', evt.data);
		ws.close();
	};

	//關閉連線
	ws.onclose = function (evt) {
		console.log('Connection closed.');
	};

7 其他

image