目录
什么是跨域
为什么会跨域
如何解决跨域
1.代理服务器
1.线上环境
2.开发环境
1.借助JSONP
2.使用CORS
3.其他方案
总结
首页 运维 nginx 如何解决跨域?常见解决方案浅析

如何解决跨域?常见解决方案浅析

Apr 25, 2023 pm 07:57 PM
前端 面试 nginx

如何解决跨域?常见解决方案浅析

跨域是开发中经常会遇到的一个场景,也是面试中经常会讨论的一个问题。掌握常见的跨域解决方案及其背后的原理,不仅可以提高我们的开发效率,还能在面试中表现的更加游刃有余。

因此今天就来和大家从前端的角度来聊聊解决跨域常见的几种方式。

什么是跨域

在讲跨域之前,我们先来看看URL的组成内容:

一个URL的组成,通常包含协议、主机名、端口号、路径、查询参数和锚点几个部分。

这里展示了一个URL的示例:

https://www.example.com:8080/path/resource.html?page=1&sort=desc#header
登录后复制

在上述示例中:
● 协议为HTTPS
● 主机名为www.example.com
● 端口号为8080
● 路径为/path/resource.html
● 查询参数为page=1&sort=desc
● 锚点为header

所谓跨域,指的是请求URL中协议、主机名、端口号中任意一个部分不相同。

以上述URL为例,下面几种写法都算是和它跨域:

http://www.example.com:8080/    // 协议不同
https://www.example.a.com:8080/ // 主机名不同
https://www.example.com:8081/   // 端口号不同
登录后复制

为什么会跨域

其实跨域问题的出现是受限于浏览器的同源策略

所谓同源策略,其实是浏览器的一种安全机制,用于限制一个网页中的网络请求仅能够访问来自同一源(域名、协议和端口号均相同)的资源,主要目的是防止恶意网站通过脚本窃取其他网站的敏感数据,保障用户的隐私和安全。

当浏览器端的脚本(js文件)访问了其他域的网络资源时,就会出现跨域问题。

如何解决跨域

前文说到,跨域问题的出现是受限于浏览器的同源策略,那么常见的解决跨域问题的方案,其实也是围绕着浏览器展开的:

1.代理服务器

在我们平常的开发中,解决跨域问题最常使用的方案是使用代理服务器

代理服务器解决跨域问题其实是抓住了同源策略只受限于浏览器访问服务器,对于服务器访问服务器并没有限制的特点,作为中间服务器做了一个请求转发的功能

具体来说,就是前端工程师编写的网页运行在由webpack等脚手架搭建的代理服务器上,当前端网页在浏览器中发起网络请求时,其实这个请求是发送到代理服务器上的,然后代理服务器会将请求转发给目标服务器,再将目标服务器返回的响应转发给客户端。

代理服务器在此过程中扮演了一个中转的角色,可以对请求和响应进行一些修改、过滤和拦截,以实现一些特定的功能。因为前端网页运行在代理服务器上,所以不存在跨域问题。

那么在线上环境和开发环境下,代理服务器是如何做请求转发的呢?

1.线上环境

在线上环境下,我们一般会采用nginx来做反向代理,从而把前端的请求转发到目标接口上。

nginx是一个轻量级高并发的web服务器,基于事件驱动,而且跨平台,window和Linux都可以进行配置。

它作为代理服务器来解决开发中的跨域问题的主要方法就是监听线上前端网址的运行端口,然后碰到包含特殊标记的请求后就进行请求转发

2.开发环境

在开发环境下,无论是借助于webpack还是使用vite或其他脚手架搭建的前端项目,解决跨域问题的核心是借助http-proxy-middleware中间件实现的。而http-proxy-middleware中间件的核心又是对http-proxy的进一步封装。

这里先展示一下在项目中使用http-proxy-middleware来实现请求转发功能的示例代码:

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = {
  server: {
    proxy: {
      // 将 /api/* 的请求代理到 http://localhost:3000/*
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: { '^/api': '/' }
      }
    }
  }
};
登录后复制

接着我们可以自己使用原生node,借助http-proxy库来搭建一个具有请求转发功能的代理服务器Demo,感兴趣的朋友可以自己测试玩玩

1. 首先需要创建一个空文件夹(全英命名)作为项目文件夹,然后使用npm init -y命令将项目升级为node的项目:

npm init -y
登录后复制

2. 接着在项目根目录下创建一个index.html文件用于发起跨域请求:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>请求转发测试</title>
</head>

<body>
    <h1>请求转发测试</h1>
    <p id="message"></p>
    <script>
        fetch(&#39;/api/login&#39;)
            .then(response => response.text())
            .then(data => {
                document.getElementById(&#39;message&#39;).textContent = data;
            });
    </script>
</body>

</html>
登录后复制

3. 接着在项目根目录下新建index.js文件来编写服务端的代码。
index.js文件是实现具有请求转发功能的代理服务器的核心文件。

const http = require(&#39;http&#39;);
const httpProxy = require(&#39;http-proxy&#39;);
const fs = require(&#39;fs&#39;);
const path = require(&#39;path&#39;);

// 创建代理服务器实例
const proxy = httpProxy.createProxyServer({});

// 创建HTTP服务器
const server = http.createServer((req, res) => {
    if (req.url === &#39;/&#39; || req.url.endsWith(&#39;.html&#39;)) {
        // 读取HTML文件
        const filename = path.join(__dirname, &#39;index.html&#39;);
        fs.readFile(filename, &#39;utf8&#39;, (err, data) => {
            if (err) {
                res.writeHead(500);
                res.end(&#39;Error reading HTML file&#39;);
            } else {
                res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/html&#39; });
                res.end(data);
            }
        });
    } else if (req.url.startsWith(&#39;/api&#39;)) {
        // 重写路径,替换跨域关键词
        req.url = req.url.replace(/^\/api/, &#39;&#39;);
        // 将请求转发至目标服务器
        proxy.web(req, res, {
            target: &#39;http://localhost:3000/&#39;,
            changeOrigin: true,
        });    
    }
});

// 监听端口
server.listen(8080, () => {
    console.log(&#39;Server started on port 8080&#39;);
});
登录后复制

4. 接着编写目标服务器target.js文件的内容,用于测试跨域访问:

const http = require(&#39;http&#39;);

const server = http.createServer((req, res) => {
    if (req.url.startsWith(&#39;/login&#39;)) {
        res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/plain&#39; });
        res.end(&#39;我是localhost主机3000端口下的方法,恭喜你访问成功!&#39;);
    } else {
        res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/plain&#39; });
        res.end(&#39;Hello, world!&#39;);
    }
});

server.listen(3000, () => {
    console.log(&#39;Target server is listening on port:3000&#39;);
})
登录后复制

5. 打开终端,输入启动目标服务器的命令:

node ./target.js //项目根目录下执行
登录后复制

6. 再开一个终端启动代理服务器,等待浏览器端发起请求就可以啦:

node ./index.js //项目根目录下执行
登录后复制

7. 最后在浏览器里访问http://localhost:8080, 打开控制台即可查看效果:

可以发现,浏览器network模块的网络请求确实是访问的8080端口的方法,但是我们的服务器默默的做了请求转发的功能,并将请求转发获取到的内容返回到了前端页面上。

其实http-proxy是对node内置库http的进一步封装,网络请求的核心部分还是使用http创建一个服务器对象去访问的。感兴趣的同学可以再读读http-proxy的源码~

除了代理服务器这种绕过浏览器同源策略的解决方式外,从前端的角度解决跨域问题还有如下一些常见的方法:

1.借助JSONP

JSONP的原理是通过动态创建

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

tomcat服务器怎么让外网访问 tomcat服务器怎么让外网访问 Apr 21, 2024 am 07:22 AM

要让 Tomcat 服务器对外网访问,需要:修改 Tomcat 配置文件,允许外部连接。添加防火墙规则,允许访问 Tomcat 服务器端口。创建 DNS 记录,将域名指向 Tomcat 服务器公有 IP。可选:使用反向代理提升安全性和性能。可选:设置 HTTPS 以提高安全性。

html文件怎么生成网址 html文件怎么生成网址 Apr 21, 2024 pm 12:57 PM

要将 HTML 文件转换为网址,需要使用网络服务器,包括以下步骤:获取网络服务器。设置网络服务器。上传 HTML 文件。创建域名。路由请求。

如何使用 PHP 部署和维护网站 如何使用 PHP 部署和维护网站 May 03, 2024 am 08:54 AM

要成功部署和维护PHP网站,需要执行以下步骤:选择Web服务器(如Apache或Nginx)安装PHP创建数据库并连接PHP上传代码到服务器设置域名和DNS监控网站维护步骤包括更新PHP和Web服务器、备份网站、监控错误日志和更新内容。

golang框架面试题集锦 golang框架面试题集锦 Jun 02, 2024 pm 09:37 PM

Go框架是一组扩展Go内置库的组件,提供预制功能(例如Web开发和数据库操作)。流行的Go框架包括Gin(Web开发)、GORM(数据库操作)和RESTful(API管理)。中间件是HTTP请求处理链中的拦截器模式,用于在不修改处理程序的情况下添加身份验证或请求日志记录等功能。Session管理通过存储用户数据来保持会话状态,可以使用gorilla/sessions管理session。

如何使用 Fail2Ban 保护服务器免受暴力攻击 如何使用 Fail2Ban 保护服务器免受暴力攻击 Apr 27, 2024 am 08:34 AM

Linux管理员的一个重要任务是保护服务器免受非法攻击或访问。默认情况下,Linux系统带有配置良好的防火墙,比如iptables、UncomplicatedFirewall(UFW),ConfigServerSecurityFirewall(CSF)等,可以防止多种攻击。任何连接到互联网的机器都是恶意攻击的潜在目标。有一个名为Fail2Ban的工具可用来缓解服务器上的非法访问。什么是Fail2Ban?Fail2Ban[1]是一款入侵防御软件,可以保护服务器免受暴力攻击。它是用Python编程语

和我一起来学习Linux安装Nginx 和我一起来学习Linux安装Nginx Apr 28, 2024 pm 03:10 PM

而今天将来一起带领大家在Linux环境安装Nginx,这里用的Linux系统是CentOS7.2.准备安装工具1.从Nginx官网下载Nginx。这里用的版本为:1.13.6.2.将下载下来的Nginx上传到Linux上,这里以/opt/nginx目录为例。运行“tar-zxvfnginx-1.13.6.tar.gz”进行解压。3.切换到/opt/nginx/nginx-1.13.6目录下,运行./configure进行初始化配置。如出现下面的提示,说明该机器没有安装PCRE,而Nginx需要依

keepalived+nginx搭建高可用几个注意点 keepalived+nginx搭建高可用几个注意点 Apr 23, 2024 pm 05:50 PM

在yum安装完keepalived之后,配置keepalived的配置文件注意点在master和backup的keepalived的配置文件中,网卡名字为当前机器的网卡名称VIP的选择为可用的一个ip,通常在做高可用,局域网环境比较多,所以这个vip是和两台机器同网段的一个内网ip。如果用在外网环境下,无所谓在不在一个网段,只要客户端能访问到。停掉nginx服务,启动keepalived服务,会看到keepalived拉动nginx服务启动若是无法启动失败,基本都是配置文件和脚本的问题,或者是防

WordPress站点文件访问受限:为什么我的.txt文件无法通过域名访问? WordPress站点文件访问受限:为什么我的.txt文件无法通过域名访问? Apr 01, 2025 pm 03:00 PM

Wordpress站点文件访问受限:排查.txt文件无法访问的原因最近有用户在配置小程序业务域名时,遇到一个问题:�...

See all articles