什么是跨域?——詳解跨域問題及其解決方案

目錄

  1. 引言
  2. 什么是跨域
  3. 同源策略
  4. 跨域的產生原因
  5. 跨域的常見解決方案
    • JSONP
    • CORS
    • 代理服務器
    • nginx反向代理
    • 后端設置允許跨域
  6. CORS的詳細實現
    • 瀏覽器中的CORS支持
    • 服務器端的CORS配置
  7. 常見的跨域場景和解決方案
    • 跨域請求API
    • 跨域加載資源
  8. 跨域的安全性考慮
  9. 跨域調試技巧
  10. 總結

引言

在現代Web開發中,前后端分離的架構設計已成為常態。然而,當前端向不同域名的后端服務器請求數據時,常會遇到跨域問題。理解并解決跨域問題,不僅能保證數據的正常交互,還能提升用戶體驗和應用的安全性。

什么是跨域

跨域(Cross-Origin)指的是瀏覽器阻止前端網頁從一個域名(Origin)向另一個域名的服務器發送請求。具體來說,一個頁面的協議、域名、端口三者任意一個與請求的目標地址不同,就被視為跨域請求。

舉例說明:

  • http://example.com 請求 http://api.example.com 會跨域,因為域名不同。
  • http://example.com 請求 https://example.com 會跨域,因為協議不同。
  • http://example.com:8080 請求 http://example.com:9090 會跨域,因為端口不同。

同源策略

同源策略(Same-Origin Policy)是瀏覽器的一個重要安全機制,防止惡意網站通過跨域方式竊取敏感數據。該策略限制了從一個源加載的文檔或腳本如何與另一個源的資源進行交互。

同源策略的定義:如果兩個URL的協議、域名和端口都相同,則這兩個URL具有相同的源。

同源策略的影響

同源策略影響以下幾類數據訪問:

  • Cookie、LocalStorage 和 IndexedDB
  • DOM 和 JavaScript 對象
  • AJAX 請求

跨域的產生原因

跨域問題主要是由于瀏覽器的同源策略所致。隨著前后端分離架構的流行,前端開發常常需要向不同域名的后端服務器請求數據,從而產生跨域問題。

跨域的常見解決方案

JSONP

JSONP(JSON with Padding)是一種傳統的跨域解決方案,通過動態創建<script>標簽來實現跨域請求,因為<script>標簽不受同源策略的限制。

實現原理

JSONP通過在URL中傳遞回調函數的名稱,后端返回對應的JavaScript代碼,前端執行該代碼,從而實現數據的獲取。

示例代碼

前端代碼:

<!DOCTYPE html>
<html>
<head><title>JSONP Demo</title>
</head>
<body><script>function handleResponse(data) {console.log('Received data:', data);}const script = document.createElement('script');script.src = 'http://example.com/api?callback=handleResponse';document.body.appendChild(script);</script>
</body>
</html>

后端代碼(假設為Node.js):

const http = require('http');http.createServer((req, res) => {const callbackName = req.url.match(/callback=([^&]+)/)[1];const responseData = { message: 'Hello, world!' };res.writeHead(200, { 'Content-Type': 'application/javascript' });res.end(`${callbackName}(${JSON.stringify(responseData)})`);
}).listen(80, 'example.com');

CORS

CORS(Cross-Origin Resource Sharing)是現代解決跨域問題的標準方法,通過HTTP頭來告訴瀏覽器,允許哪些跨域請求。

實現原理

CORS通過設置HTTP響應頭Access-Control-Allow-Origin,告訴瀏覽器哪些域名可以訪問資源。

示例代碼

前端代碼:

fetch('http://api.example.com/data', {method: 'GET',headers: {'Content-Type': 'application/json'}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

后端代碼(假設為Node.js和Express):

const express = require('express');
const app = express();app.use((req, res, next) => {res.header('Access-Control-Allow-Origin', '*');res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');next();
});app.get('/data', (req, res) => {res.json({ message: 'Hello, world!' });
});app.listen(80, 'example.com');

代理服務器

代理服務器可以繞過瀏覽器的同源策略,將跨域請求轉發到目標服務器。

示例代碼

前端代碼:

fetch('/api/data', {method: 'GET',headers: {'Content-Type': 'application/json'}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

后端代碼(假設為Node.js和Express):

const express = require('express');
const request = require('request');
const app = express();app.use('/api', (req, res) => {const url = 'http://api.example.com' + req.url;req.pipe(request(url)).pipe(res);
});app.listen(3000, () => {console.log('Proxy server running on port 3000');
});

nginx反向代理

通過配置nginx反向代理,也可以實現跨域請求。

配置示例
server {listen 80;location /api/ {proxy_pass http://api.example.com/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}

后端設置允許跨域

通過在后端設置CORS響應頭,允許特定域名訪問資源。

示例代碼

后端代碼(假設為Spring Boot):

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Beanpublic WebMvcConfigurer corsConfigurer() {return new WebMvcConfigurer() {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://example.com").allowedMethods("GET", "POST", "PUT", "DELETE").allowedHeaders("*").allowCredentials(true);}};}
}

CORS的詳細實現

瀏覽器中的CORS支持

CORS在瀏覽器中的實現是通過在請求和響應中添加相應的HTTP頭部字段來完成的。常見的CORS相關頭部字段包括:

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Credentials
  • Access-Control-Expose-Headers

服務器端的CORS配置

不同的后端框架和服務器有不同的CORS配置方法。以下是一些常見的配置示例。

Node.js和Express
const express = require('express');
const cors = require('cors');
const app = express();app.use(cors());app.get('/data', (req, res) => {res.json({ message: 'Hello, world!' });
});app.listen(80, () => {console.log('Server running on port 80');
});
Spring Boot
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Beanpublic WebMvcConfigurer corsConfigurer() {return new WebMvcConfigurer() {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://example.com").allowedMethods("GET", "POST", "PUT", "DELETE").allowedHeaders("*").allowCredentials(true);}};}
}

常見的跨域場景和解決方案

跨域請求API

當前端請求不同域名的API時,需要解決跨域問題。可以通過CORS、JSONP或代理服務器等方法來實現。

跨域加載資源

跨域加載資源(如圖片、腳本、樣式表等)時,同樣需要解決跨域問題。通常通過CORS頭部來允許跨域加載。

跨域的安全性考慮

跨域請求涉及安全性問題,特別是當允許外部網站訪問敏感數據時。以下是一些安全性考慮:

  • 僅允許可信任的域名進行跨域請求。
  • 使用Access-Control-Allow-Credentials頭部來限制跨域請求的憑證傳遞。
  • 避免通過JSONP傳遞敏感數據。

跨域調試技巧

在調試跨域問題時,可以使用以下技巧:

  • 使用瀏覽器的開發者工具查看請求和響應頭部。
  • 使用代理服務器或nginx進行本地調試。
  • 查看后端服務器的日志,確認CORS配置是否正確。

總結

跨域問題是Web開發中常見的問題,理解跨域的原理及其解決方案對于前后端分離開發尤為重要。本文詳細介紹了跨域的概念、同源策略、跨域的產生原因及常見的解決方案,包括JSONP、CORS、代理服務器、nginx反向代理等。通過合理配置和編寫代碼,我們可以有效地解決跨域問題,確保前后端數據的正常交互。

希望本文能幫助您深入理解跨域問題及其解決方案。如果您有任何問題或建議,歡迎在評論區留言討論。

Happy Coding!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40583.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40583.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40583.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python+playwright 學習-90 and_ 和 or_ 定位

前言 playwright 從v1.34 版本以后支持and_ 和 or_ 定位 XPath 中的and和or xpath 語法中我們常用的有text()、contains() 、ends_with()、starts_with() //*[text()="文本"] //*[contains(@id, "xx")] //

LLM - 循環神經網絡(RNN)

1. RNN的關鍵點&#xff1a;即在處理序列數據時會有順序的記憶。比如&#xff0c;RNN在處理一個字符串時&#xff0c;在對字母表順序有記憶的前提下&#xff0c;處理這個字符串會更容易。就像人一樣&#xff0c;讀取下面第一個字符串會更容易&#xff0c;因為人對字母出現的順序…

idea MarketPlace插件找不到

一、背景 好久沒用idea了&#xff0c;打開項目后沒有lombok&#xff0c;安裝lombok插件時發現idea MarketPlace插件市場找不到&#xff0c;需要重新配置代理源&#xff0c;在外網訪問時通過代理服務進行連接 二、操作 ### File-->setting 快捷鍵 Ctrl Alt S 遠端源地…

動手學深度學習(Pytorch版)代碼實踐 -循環神經網絡-53語言模型和數據集

53語言模型和數據集 1.自然語言統計 引入庫和讀取數據&#xff1a; import random import torch from d2l import torch as d2l import liliPytorch as lp import numpy as np import matplotlib.pyplot as plttokens lp.tokenize(lp.read_time_machine())一元語法&#xf…

類和對象深入理解

目錄 static成員概念靜態成員變量面試題補充代碼1代碼2代碼3如何訪問private中的成員變量 靜態成員函數靜態成員函數沒有this指針 特性 友元友元函數友元類 內部類特性1特性2 匿名對象拷貝對象時的一些編譯器優化 感謝各位大佬對我的支持,如果我的文章對你有用,歡迎點擊以下鏈接…

Linux-DNS

DNS域名解析服務 1.DNS介紹 DNS 是域名系統 (Domain Name System) 的縮寫&#xff0c;是因特網的一項核心服務&#xff0c;它作為可以將域名和IP地址相互映射的一個分布式數據庫&#xff0c;能夠使人更方便的訪問互聯網&#xff0c;而不用去記住能夠被機器直接讀取的IP數串。…

大氣熱力學(2)——熱力學基礎

本篇文章源自我在 2021 年暑假自學大氣物理相關知識時手寫的筆記&#xff0c;現轉化為電子版本以作存檔。相較于手寫筆記&#xff0c;電子版的部分內容有補充和修改。筆記內容大部分為公式的推導過程。 文章目錄 2.0 本文所用符號一覽2.1 準靜態過程2.2 熱量和熱容量2.2.1 熱量…

Java對象

面向對象和面向過程的區別 兩者的主要區別在于解決問題的方式不同 面向過程把解決問題的過程拆成一個個方法&#xff0c;通過一個個方法的執行解決問題。 面向對象會先抽象出對象&#xff0c;然后用對象執行方法的方式解決問題。 另外&#xff0c;面向對象開發的程序一般更易維…

乞丐傳武功

題目 你施舍給了路邊的乞丐兩個饅頭&#xff0c;誰料這個乞丐其實是隱士高人。為了回報你的善心&#xff0c;只見他緩緩從懷中掏出了數本武功秘籍&#xff0c;讓你從中挑選一本。你珍重地接過這些秘籍&#xff0c;目光掃過每本封面&#xff0c;降龍十八掌、神照經、易筋經、凌…

[FreeRTOS 基礎知識] 互斥量 概念

文章目錄 基礎知識互斥量互斥量與信號量區別優先級反轉優先級繼承小結 基礎知識 [FreeRTOS 基礎知識] 信號量 概念 互斥量 互斥量&#xff08;Mutex&#xff0c;全稱&#xff1a;Mutual Exclusion&#xff09;&#xff0c;在計算機科學中&#xff0c;是一種用于防止多個進程同…

科研繪圖系列:R語言實驗結果組圖(linechart + barplot)

介紹 實驗結果的多樣性意味著每個結果都可能揭示研究的不同方面或角度。在科學研究和數據分析中,通常我們會收集一系列數據點,每個數據點都對應著實驗的一個特定變量或條件。為了全面理解這些數據,我們可能會采用多種可視化技術來展示它們。 將多個結果分別可視化,可以讓…

親子時光里的打臉高手,賈乃亮與甜馨的父愛如山

賈乃亮這波操作&#xff0c;簡直是“實力打臉”界的MVP啊&#xff01; 7月5號&#xff0c;他一甩手&#xff0c;甩出張合照&#xff0c; 瞬間讓多少猜測紛飛的小伙伴直呼&#xff1a;“臉疼不&#xff1f;”帶著咱家小甜心甜馨&#xff0c; 回了哈爾濱老家&#xff0c;這趟親…

Nginx(http配置、https配置)訪問Spring Boot 項目

前文 記錄一下在linux服務器下配置nginx中nginx.conf文件代理訪問springboot項目 1. spring boot.yml配置 其他mysql,redis,mybatis等之類的配置就不一一列出了 # 自定義配置 為了等下驗證讀取的配置文件環境 appName: productserver:port: 8083 # 應用服務 WEB 訪問端口s…

SQL窗口函數詳解

詳細說明在sql中窗口函數是什么&#xff0c;為什么需要窗口函數&#xff0c;有普通的聚合函數了那窗口函數的意義在哪&#xff0c;窗口函數的執行邏輯是什么&#xff0c;over中的字句是如何使用和理解的&#xff08;是不是句句戳到你的痛點&#xff0c;哼哼&#xff5e;&#x…

C語言編譯和編譯預處理

編譯預處理 ? 編譯是指把高級語言編寫的源程序翻譯成計算機可識別的二進制程序&#xff08;目標程序&#xff09;的過程&#xff0c;它由編譯程序完成。 ? 編譯預處理是指在編譯之前所作的處理工作&#xff0c;它由編譯預處理程序完成 在對一個源程序進行編譯時&#xff0c;…

全國青少年軟件編程等級考試-四級-奇偶之和(真題)

題目&#xff1a;奇偶之和 1.準備工作 (1)保留舞臺中的小貓角色&#xff1b; 2.功能實現 (1)分別計算1&#xff5e;100中&#xff0c;奇數之和&#xff0c;偶數之和&#xff1b; (2)說出奇數之和&#xff0c;偶數之和。 講解&#xff1a; 1、如何判斷奇偶數 奇數是指除以2有…

C++deque容器

文章目錄 deque容器概念deque操作deque對象的帶參數構造deque頭部和末尾的添加移除操作deque的數據存取deque與迭代器deque賦值deque插入deque刪除 deque容器概念 deque是雙端數組&#xff0c;而vector是單端的。 ?deque頭部和尾部添加或移除元素都非常快速, 但是在中部安插元…

在x86/amd64的機器上使用Docker運行arm64v8/ubuntu并安裝ROS1

一、準備工作 主要是因為國內網絡的問題&#xff0c;可能導致鏡像拉取失敗&#xff0c;解決辦法參考&#xff1a;鏡像加速 二、安裝運行過程 2.1拉取鏡像&#xff1a; sudo docker pull arm64v8/ubuntu:20.04這個是ubuntu的拉取指令&#xff0c;其他的也是類似。 2.2 運行…

【DevOps】運維過程中經常遇到的Http錯誤碼問題分析(一)

一、解決HTTP 408錯誤&#xff1a;上傳3M文件時請求超時的問題 在開發Web應用程序時&#xff0c;遇到HTTP 408狀態碼&#xff08;請求超時&#xff09;是常見的問題。特別是在上傳大文件時&#xff0c;這種情況更容易發生。本文將探討在上傳一個3M文件時&#xff0c;Web服務器…

LeetCode題練習與總結:排序鏈表--148

一、題目描述 給你鏈表的頭結點 head &#xff0c;請將其按 升序 排列并返回 排序后的鏈表 。 示例 1&#xff1a; 輸入&#xff1a;head [4,2,1,3] 輸出&#xff1a;[1,2,3,4]示例 2&#xff1a; 輸入&#xff1a;head [-1,5,3,4,0] 輸出&#xff1a;[-1,0,3,4,5]示例 3&am…