当前位置: 首页 > news >正文

八、浏览器同源策略

上一篇👉: 浏览器垃圾回收机制

文章目录

  • 浏览器同源策略
    • 1.同源策略的定义
    • 2.同源策略的作用
    • 3.同源策略的限制范围
    • 4.解决跨域方案汇总
      • 1.CORS(跨源资源共享)
      • 2.JSONP
      • 3.postMessage 跨域
      • 4.Nginx代理跨域
      • 5.Node.js中间件代理跨域
      • 6.document.domain + iframe
      • 7.Location.hash + iframe
      • 8.window.name + iframe跨域
      • 9.WebSocket协议跨域
    • 5.正向代理与反向代理的区别
      • 正向代理(Forward Proxy)
      • 反向代理(Reverse Proxy)
      • 核心差异
    • 6.Nginx
      • Nginx概念及工作原理
      • 核心特性
      • 架构层次
      • Master Process(主进程)
      • Worker Processes(工作进程)
      • 工作流程

浏览器同源策略

1.同源策略的定义

同源策略(Same-origin policy)是Web浏览器为保护用户信息安全而实施的一种重要安全策略。该策略规定,Web浏览器允许来自同一源的文档或脚本访问彼此的资源,但限制了来自不同源的交互。这里的“源”指的是协议、域名和端口号三者的组合。如果三个要素完全一致,则视为同源;有任何一个不相同,则视为跨域。

2.同源策略的作用

  • 保护用户数据:防止恶意网站读取另一个网站的敏感数据,如Cookies、存储在浏览器中的用户个人资料等。
  • 防止恶意脚本执行:阻止不同源的脚本相互操作,防止恶意脚本注入和执行,保护用户的浏览环境安全。

3.同源策略的限制范围

同源策略主要在以下几个方面实施限制:

  • JavaScript访问权限:禁止脚本读取或修改不同源页面的DOM,也无法向不同源的服务器发送Ajax请求(除非目标服务器明确允许跨域)。
  • Cookie、LocalStorage和IndexedDB访问:禁止脚本访问不同源的这些存储数据,保护用户数据不被非法窃取或篡改。
  • 其他API限制:包括Web Storage、Web Workers、Fetch API等现代Web
    API在内,大多遵循同源策略,限制跨域访问。

4.解决跨域方案汇总

1.CORS(跨源资源共享)

CORS(跨域资源共享)是一种机制,确保了网页可以从不同源(协议、域名、端口)的服务器上获取资源,而不会受到浏览器同源策略的限制。这一机制通过在HTTP请求和响应中加入特定的头部信息来工作,从而允许或拒绝跨域请求。

  • 简单请求
    简单请求的特点是使用了GET、HEAD或POST方法,并且HTTP头部信息限于几个特定字段。这类请求不会触发预检请求(preflight request),浏览器直接发起请求,并在请求头中加入Origin字段,表明请求源。服务器需要在响应中包含Access-Control-Allow-Origin头部,以明确允许的请求源。对于简单请求,服务器至少需要配置Access-Control-Allow-Origin字段。

  • 非简单请求
    包括使用了除GET、HEAD、POST之外的方法(如DELETE、PUT),或POST请求中包含非标准的内容类型、自定义请求头等。这类请求会在正式请求前先发送一个OPTIONS请求作为预检请求,以确认实际请求是否安全可接受。预检请求会携带Origin、Access-Control-Request-MethodAccess-Control-Request-Headers等头部。服务器需响应这些头部对应的允许值,至少包括Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers

  • Cookie处理
    要在CORS请求中携带Cookie,需满足以下条件:

    • 客户端(如通过XMLHttpRequest或Fetch API)需设置withCredentials属性为true,表明请求需要携带凭据(如Cookie)。
    • 服务器响应中必须设置Access-Control-Allow-Credentials为true,表明服务器允许浏览器携带Cookie。
    • Access-Control-Allow-Origin不能设为星号*,而应指定具体的源地址,因为星号不允许与Access-Control-Allow-Credentials: true一起使用。
  • 减少OPTIONS请求
    为了优化性能,可以通过在服务器响应中设置Access-Control-Max-Age头部来缓存预检请求的结果,避免每次请求都发送OPTIONS请求。该值指定了预检请求结果的有效期,单位为秒。

总之,CORS通过一系列HTTP头部的精确控制,实现了安全的跨域数据交互,同时提供了灵活的配置选项以适应不同场景的安全需求和性能优化。

2.JSONP

JSONP(JSON with Padding)是一种跨域数据交互技术,其原理基于浏览器对 <script> 标签的特性和同源策略的绕过。

原理:JSONP利用了浏览器对<script>标签的特殊处理:通过动态创建<script>元素并设置其src属性为包含API请求的URL,由于<script>标签的资源请求不受同源策略限制,因此可以实现跨域数据请求。请求URL中通常包含一个查询参数,用于指定客户端期望调用的回调函数名称。服务器接收到请求后,会将响应数据包裹在这个回调函数中返回,从而在客户端执行并传递数据。

JavaScript实现

<script>// 创建script元素var script = document.createElement('script');script.type = 'text/javascript';// 设置src属性,包含请求URL及回调函数名script.src = 'http://www.example.com/api/data?callback=myCallback';// 将script元素插入页面,触发请求document.head.appendChild(script);// 定义回调函数处理服务器返回的数据function myCallback(data) {console.log(data);}
</script>

服务器响应内容示例:

myCallback({"status": "success", "message": "Hello, World!"});

Vue中使用axios实现JSONP
在Vue项目中,虽然axios本身不直接支持JSONP,但可以通过封装或使用第三方库如vue-jsonp来实现。这里提供一个简化的示例说明如何模拟实现:

// 注意:实际开发中应使用专门的库或封装方法
this.$http.jsonp('http://www.example.com/api/data', {params: {callback: 'myCallback'}
}).then((res) => {console.log(res.data); 
})

后端Node.js示例
后端需要解析请求中的回调函数名,并将响应数据封装进该函数返回。

const http = require('http');
const querystring = require('querystring');const server = http.createServer((req, res) => {let params = querystring.parse(req.url.split('?')[1]);let callback = params.callback;// 假设这是从数据库获取的数据let data = {"status": "success", "data": "Sample Data"};// 构造JSONP响应res.writeHead(200, {'Content-Type': 'application/javascript'});res.end(`${callback}(${JSON.stringify(data)})`);
});server.listen(8080, () => {console.log('Server running on port 8080');
});

JSONP的缺点

  1. 仅支持GET请求:因为数据是通过URL查询参数传递的,这限制了其适用场景,不适合大型数据传输或涉及敏感信息的请求。
  2. 安全性问题:容易受到XSS(跨站脚本攻击)的威胁,恶意脚本可能通过构造特殊的回调函数名注入执行。
  3. 无错误处理机制:相比现代的CORS等技术,JSONP缺乏标准化的错误处理流程,调试和错误报告较为困难。

3.postMessage 跨域

postMessage 是一种允许来自不同源的脚本采用异步方式进行有限通信的Web API。这一功能对于实现跨域消息传递至关重要,尤其是在涉及iframe、窗口以及Web Worker之间的通信场景。

概念:postMessage 方法允许一个窗口(或iframe)向另一个窗口(或iframe)发送消息,即使这两个窗口(或iframe)来源于不同的源(协议+域名+端口)。这对于实现跨域通信是非常有用的技术,因为它不受到同源策略的限制。

用法:postMessage 方法接收两个参数:

  • data:要发送的数据。根据HTML5规范,它可以是任何基本类型或可复制的对象,但在某些较旧的浏览器中,可能只支持字符串。因此,最佳实践是使用JSON.stringify()将对象转换为字符串。
  • origin:指定哪些源的窗口应该接收消息。可以设置为特定的源(如 ‘http://example.com’),或者使用通配符 *
    来允许任何源接收消息(但这存在安全风险,应谨慎使用)。若要限定与当前窗口同源,则可设置为 /

应用场景

  • 页面与其打开的新窗口间的数据传递
  • 多个窗口间的消息传递
  • 主页面与嵌入的iframe间的消息传递

示例
sender.html (位于 domain1.com/sender.html):

<iframe id="iframe" src="http://www.domain2.com/receiver.html" style="display:none;"></iframe>
<script>var iframe = document.getElementById('iframe');iframe.onload = function() {var message = {content: 'Hello from sender!'};iframe.contentWindow.postMessage(JSON.stringify(message), 'http://www.domain2.com');window.addEventListener('message', function(e) {if (e.origin === 'http://www.domain2.com') {alert('Response from receiver: ' + e.data);}}, false);};
</script>

receiver.html (位于 domain2.com/receiver.html):

<script>window.addEventListener('message', function(e) {if (e.origin === 'http://www.domain1.com') {alert('Message received from sender: ' + e.data);var response = {content: 'Hello back to sender!',original: JSON.parse(e.data)};e.source.postMessage(JSON.stringify(response), e.origin);}}, false);
</script>

注意事项

  • 在使用postMessage时,确保正确验证消息来源(即检查event.origin属性),以防止跨站脚本攻击(XSS)。
  • 消息接收方通过监听message事件来接收消息,其中event.data包含发送的数据,而event.origin则标识发送消息的源。

使用e.source.postMessage()而不是window.parent.postMessage()可以更灵活地处理消息的回传,特别是在多个窗口或iframe结构中。

4.Nginx代理跨域

使用Nginx作为代理服务器解决跨域问题,主要利用其强大的反向代理能力和对HTTP头部的灵活控制能力,实现跨源资源共享(CORS)。以下是两种常见的应用场景及其解决方案:

  1. Nginx配置解决iconfont跨域问题
    当静态资源服务器需要向不同源的客户端提供iconfont字体文件(如.eot、.otf、.ttf、.woff、.svg格式)时,虽然大部分静态资源不受同源策略限制,但这些字体文件可能因浏览器的安全策略遇到跨域问题。通过在Nginx配置中添加适当的Access-Control-Allow-Origin头部,可以允许所有源访问这些字体文件,从而解决跨域问题。
location / {add_header Access-Control-Allow-Origin *;
}

这段配置表示对所有请求到该Nginx服务器的资源,响应头中都会包含Access-Control-Allow-Origin: *,允许任何源的请求访问。

  1. Nginx反向代理解决接口跨域问题
    对于前后端分离的应用,尤其是前端请求不同源后端接口的情况,可以通过Nginx设置反向代理来规避浏览器的同源策略限制。
    实现思路是设置一个与前端同源(域名相同,端口可以不同)的Nginx代理服务器,该服务器接收前端的请求,然后作为“中转站”去访问实际后端服务(domain2),并将后端响应转发回前端。这样,从浏览器的角度看,请求和响应都在同一个源下,避免了跨域问题。
server {listen       81; # 代理服务器监听的端口server_name  www.domain1.com; # 与前端同源的域名location / {proxy_pass   http://www.domain2.com:8080;  # 反向代理至实际后端接口地址proxy_cookie_domain www.domain2.com www.domain1.com; # 修改响应中Set-Cookie的Domain属性,使前端能正确保存cookie# 当前端请求需要带cookie且涉及到跨域时,需要设置如下头部add_header Access-Control-Allow-Origin http://www.domain1.com; # 允许特定源的跨域请求add_header Access-Control-Allow-Credentials true; # 允许携带凭证(如cookies)# 如果前端请求不涉及cookie,可以简化为# add_header Access-Control-Allow-Origin *;}
}

这段配置不仅实现了接口的跨域访问,还通过proxy_cookie_domain指令修改了后端返回的Cookie中Domain属性,确保了前端能够正确存储和使用这些Cookie,这对于需要认证或状态保持的场景尤为重要。

请注意,当设置Access-Control-Allow-Credentials为true时,Access-Control-Allow-Origin不能设置为*,而应指定确切的源地址,以确保安全性。

5.Node.js中间件代理跨域

在Node.js中使用中间件实现跨域代理,是一种常见的处理前后端分离项目中跨域请求问题的方法。此方法通过在Node.js服务器上部署一个代理层,将前端的跨域请求转发到目标后端服务器,有效绕过了浏览器的同源策略限制。下面分别介绍非Vue框架和Vue框架下的跨域代理实现方式。

  1. 非Vue框架下的跨域代理

使用Express框架配合http-proxy-middleware中间件可以快速搭建一个代理服务器,用于转发前端请求到后端API服务器,并处理跨域问题。

前端请求示例:

var xhr = new XMLHttpRequest();
xhr.withCredentials = true; // 允许携带cookie
xhr.open('GET', 'http://www.domain1.com:3000/login?user=admin', true);
xhr.send();

Node.js服务器配置:

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();app.use('/', createProxyMiddleware({target: 'http://www.domain2.com:8080', // 目标API服务器地址changeOrigin: true, // 改变请求源头,模拟从代理服务器发起请求onProxyRes: function(proxyRes, req, res) {res.header('Access-Control-Allow-Origin', 'http://www.domain1.com'); // 设置允许的源res.header('Access-Control-Allow-Credentials', 'true'); // 允许携带凭证},cookieDomainRewrite: 'www.domain1.com', // 修改响应中Cookie的Domain
}));app.listen(3000, () => {console.log('Proxy server is running on port 3000');
});
  1. Vue框架下的跨域代理

在Vue项目开发过程中,通常会使用Webpack作为打包工具,webpack-dev-server提供了内置的代理功能,可以直接在webpack.config.js中配置接口代理,简化跨域处理流程。

webpack.config.js配置示例:

module.exports = {// ...其他配置devServer: {historyApiFallback: true,proxy: {'/login': { // 匹配的路径target: 'http://www.domain2.com:8080', // 目标API服务器地址changeOrigin: true, // 改变请求源头secure: false, // 如果是HTTPS接口,需要设置为falsecookieDomainRewrite: 'www.domain1.com', // 修改响应中Cookie的Domain}},noInfo: true // 减少输出信息}
};

在Vue项目的开发环境下,通过上述配置,webpack-dev-server会自动拦截前端向/login路径的请求,并将其代理到指定的后端API服务器,同时处理好跨域问题,使得开发者可以无缝对接后端接口进行开发调试,而无需关心跨域问题。

6.document.domain + iframe

在Web开发中,当遇到主域相同但子域不同的跨域问题时,可以通过修改document.domain属性的方法结合<iframe>标签来实现跨域通信。这种方法适用于那些拥有共同顶级域名的页面间的通信需求。具体实施步骤如下:

实现原理:
设置document.domain: 两个页面——即父页面和子页面(通过<iframe>嵌入)——都需要通过JavaScript设置它们的document.domain属性为相同的高级别主域。这样做是为了让浏览器认为这两个页面处于同一个域下,从而绕过同源策略的限制。

应用场景:
限制条件: 此方案仅适用于主域名相同,但子域名不同的场景。例如,a.example.com和b.example.com可以使用此方法通信,但example.com与anotherexample.com则不适用。

示例代码
父窗口页面 (domain.com/a.html):

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Parent Window</title>
</head>
<body><iframe id="iframe" src="http://child.domain.com/b.html"></iframe><script>document.domain = 'domain.com'; // 设置document.domain为共同的基础主域var user = 'admin'; // 父窗口定义的变量</script>
</body>
</html>

子窗口页面 (child.domain.com/b.html):

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Child Window</title>
</head>
<body><script>document.domain = 'domain.com'; // 子窗口同样设置document.domain为共同的基础主域// 从父窗口获取变量console.log('获取父窗口数据: ' + window.parent.user);</script>
</body>
</html>

注意事项

  • 安全考量: 虽然此方法可以解决特定条件下的跨域问题,但在实施前需仔细考虑安全因素,确保不会无意间暴露敏感信息或引入安全漏洞。
  • 适用范围: 仅限于同主域名下的子域名相互通讯,对于完全不同域名间的跨域问题无效。
  • 现代替代方案:随着CORS(跨源资源共享)和WebSocket等技术的发展,对于跨域数据交换的需求,更多地倾向于使用这些现代标准,因为它们提供了更为灵活和安全的跨域通信机制。

7.Location.hash + iframe

在早期的Web开发中,为了解决跨域通信问题,开发者常采用location.hash + iframe的技巧,这是一种较为原始且有限制的跨域通讯方法。这种方法通过URL的hash部分传递信息,利用不同页面间的iframe元素和同源策略的特性,实现在一定条件下的跨域数据交换。以下是该方法的具体实施步骤和示例代码的描述:

实现原理

  • 借助iframe和hash值传递信息:不同源的页面间不能直接进行JavaScript通信,但可以通过iframe加载另一个页面,并利用URL的hash部分传递数据。因为改变iframe的src的hash部分不会引起页面刷新,且hash变化会触发onhashchange事件,这为跨域数据传输提供了可能。
  • 中间人页面:在两个不同源的页面A和B之间,通常需要一个同源于A的中间页面C来完成闭环通信。C页面可以访问A页面的JavaScript上下文,从而实现数据的最终传递。

具体实现步骤:
a.html (位于 domain1.com)

  • 创建一个隐藏的iframe,其src指向B域的b.html。
  • 通过setTimeout设置延迟,改变iframe的src,附加hash值(如#user=admin),以此向B域的页面传递信息。
  • 定义一个全局函数onCallback,供同源的C页面调用来回传数据。

b.html (位于 domain2.com)

  • 同样包含一个隐藏的iframe,其src指向A域的c.html。
  • 监听自身的onhashchange事件,一旦hash值发生变化(即接收到A域传来的信息),立即将此hash值附加到C页面的iframe src中,间接传递给C页面。

c.html (位于 domain1.com)

  • 作为同源于A页面的中间人,监听自身的onhashchange事件。
  • 解析接收到的hash值,通过window.parent.parent访问到A页面的上下文,并调用预先定义好的onCallback函数,将处理后的信息回传给A页面。

示例代码摘要:
a.html:

<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>var iframe = document.getElementById('iframe');setTimeout(function() {iframe.src += '#user=admin';}, 1000);function onCallback(res) {alert('Data from c.html ---> ' + res);}
</script>

b.html:

<iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;"></iframe>
<script>var iframe = document.getElementById('iframe');window.onhashchange = function () {iframe.src += location.hash;};
</script>

c.html:

<script>window.onhashchange = function () {var res = 'hello: ' + location.hash.replace('#user=', '');window.parent.parent.onCallback(res);};
</script>

注意事项

  • 此方法受限于同源策略,且通信效率较低,用户体验可能受影响。
  • 现代Web开发中,更推荐使用CORS(跨源资源共享)、WebSockets或Fetch API等技术来处理跨域问题,它们提供更强大、灵活且安全的跨域通信能力 。

8.window.name + iframe跨域

利用 window.name 和 iframe 实现跨域通信是一种巧妙的技术手段,尤其适用于那些受到同源策略限制的场景。这种方法的核心在于利用了 window.name 属性的两个特性:一是其值在页面跳转时可以保持不变,即使跳转到完全不同域名的页面;二是它可以存储异常大量的数据(理论上可达2MB),这为跨域数据交换提供了便利。
a.html (domain1.com/a.html)

var proxy = function(url, callback) {var state = 0;var iframe = document.createElement('iframe');iframe.src = url; // 设置iframe的src为跨域页面iframe.onload = function() {if (state === 1) {// 第二次加载(同域proxy页面)完成,读取并处理数据callback(iframe.contentWindow.name);destroyFrame();} else if (state === 0) {// 第一次加载(跨域页面)成功,转向同域代理页面iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';state = 1;}};document.body.appendChild(iframe);function destroyFrame() {iframe.contentWindow.document.write('');iframe.contentWindow.close();document.body.removeChild(iframe);}// 请求跨域b页面的数据proxy('http://www.domain2.com/b.html', function(data) {alert(data); // 数据展示或进一步处理});
};

proxy.html (domain1.com/proxy.html)
此页面仅作为中转站,确保跨域数据能通过同源策略传递回主页面。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Proxy Page</title>
</head>
<body>
<!-- 此页面无需任何额外代码,为了作为同源策略下的数据中转 -->
<!-- 跨域数据在window.name中已准备好,将被父页面通过iframe访问 -->
</body>
</html>

b.html (domain2.com/b.html)

<script>window.name = 'This is domain2 data!'; // 跨域数据存储于window.name
</script>
  1. 工作原理 起始:a.html 使用 proxy 函数创建 iframe,指向跨域的 b.html。
  2. 数据载入:b.html 将数据写入 window.name。
  3. 回程代理:首次加载完毕后,iframe 的 src 被重定向到同域的 proxy.html,此时 window.name
    的数据依然保留。
  4. 数据提取与处理:proxy.html 加载时(第二次 onload 触发),因同源关系,可以从 iframe 提取
    window.name 中的数据并通过回调函数返回给 a.html。
  5. 资源清理:数据处理完毕后,iframe 被销毁,确保安全及资源管理。

安全考量
尽管此技术可规避浏览器的跨域访问限制,但实施时务必重视数据的安全性和隐私保护,确保跨域通信活动遵循网络安全最佳实践和法规要求。

9.WebSocket协议跨域

WebSocket协议是一种在HTML5中引入的通信协议,它允许浏览器和服务器之间建立全双工、低延迟的通信渠道,特别适用于实现实时交互和服务器推送技术。相较于传统的HTTP请求,WebSocket能够维持长时间的连接状态,且双向通信无需重复握手,提高了效率和实时性。此协议还支持跨域通信,打破了同源策略的限制,使得不同源的客户端与服务器能直接进行数据交换。

为了简化WebSocket的使用,通常会采用如Socket.io这样的库,它不仅对WebSocket API进行了高级封装,提供了更易于使用的接口,还对不兼容WebSocket的旧版浏览器提供了向下兼容的支持。

客户端(前端)代码示例
HTML部分包含一个文本输入框供用户输入数据,JavaScript部分则通过Socket.io与服务器建立WebSocket连接。

<!-- HTML部分 -->
<div>用户输入:<input type="text"></div><!-- 引入Socket.io库 -->
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script><!-- JavaScript部分 -->
<script>// 创建Socket.io实例并连接到服务器var socket = io('http://www.domain2.com:8080');// 监听连接成功的事件socket.on('connect', function() {// 监听来自服务器的消息socket.on('message', function(msg) {console.log('从服务器收到的数据: ---> ' + msg);});// 监听服务器断开连接的事件socket.on('disconnect', function() {console.log('服务器连接已关闭.');});});// 当用户在输入框中失去焦点时,发送输入值到服务器document.getElementsByTagName('input')[0].onblur = function() {socket.send(this.value);};
</script>

服务器端(Node.js)代码示例
使用Node.js和Socket.io创建一个简单的WebSocket服务器,监听8080端口,并处理客户端的连接与消息。

// 引入必要的模块
var http = require('http');
var socket = require('socket.io');// 创建HTTP服务器
var server = http.createServer(function(req, res) {res.writeHead(200, {'Content-type': 'text/html'});res.end();
});// 服务器监听8080端口
server.listen(8080);
console.log('服务器正在8080端口运行...');// 使用Socket.io监听服务器上的WebSocket连接
socket.listen(server).on('connection', function(client) {// 接收到客户端消息时的处理client.on('message', function(msg) {// 向客户端回复消息client.send('你好:' + msg);console.log('从客户端收到的数据: ---> ' + msg);});// 处理客户端断开连接client.on('disconnect', function() {console.log('客户端连接已关闭.');});
});

以上示例展示了如何利用Socket.io在前端和后端之间快速搭建WebSocket通信,包括如何处理连接、消息收发和断开连接等核心功能。

5.正向代理与反向代理的区别

特性正向代理反向代理
目的允许客户端通过代理访问受限资源提高服务端性能,负载均衡,隐藏后端服务器
设置方客户端服务器端
代理对象客户端(隐藏客户端)服务器(隐藏服务器)
透明性需客户端配置,不透明对客户端透明,无需客户端配置
配置需求修改客户端网络设置(如浏览器)修改DNS指向代理服务器,客户端无感知
应用场景访问控制、隐私保护、地域限制突破负载均衡、SSL终止、安全防护、CDN
示例个人使用代理服务器浏览国外网站Nginx作为网站前端,分配请求到后端服务器

正向代理(Forward Proxy)

  • 目的:帮助客户端访问受限资源。当客户端因网络策略、地理位置限制等原因无法直接访问目标服务器时,正向代理作为中介,接收客户端的请求,然后转发给目标服务器,并将服务器响应传回客户端。
  • 设置方:由客户端负责配置代理服务器信息,可能涉及修改浏览器或其他客户端应用的网络设置。
  • 作用:隐藏客户端的真实身份,对外展现的是代理服务器的IP地址。
  • 配置需求:需要在客户端进行代理服务器的配置。

反向代理(Reverse Proxy)

  • 目的:优化服务端架构,提高服务的可用性和安全性。反向代理服务器接收来自客户端的请求,根据预定义的规则决定将请求分配给后端的哪一个服务器处理,随后将服务器响应返回给客户端。
  • 设置方:由服务器端部署和管理,对客户端透明。
  • 作用:隐藏后端服务器的具体信息,提供统一的入口,实现负载均衡、SSL终止、缓存及安全防护等功能。
  • DNS配置:通常通过修改DNS记录,使域名解析到反向代理服务器的IP地址,客户端无需知晓后端服务器的细节。

正向代理流程:👇正向代理流程描述了客户端通过配置的代理服务器(Proxy)向目标服务器(Target_Server)请求数据的过程。

发出请求
转发请求
响应数据
返回数据给客户端
Client
Proxy
Target_Server

反向代理流程:👇反向代理流程则展示了客户端请求通过反向代理服务器(Reverse_Proxy),该代理服务器根据策略选择合适的真实服务器(Real_Server)处理请求,并将响应返回给客户端的场景。

发出请求
智能路由到
处理并响应
返回响应给客户端
Client
Reverse_Proxy
Real_Server

核心差异

尽管正向代理和反向代理在结构上都表现为 client-proxy-server,但关键区别在于代理服务器的部署位置和代理服务的目标:

  • 部署位置:正向代理靠近客户端,由客户端配置使用;反向代理则部署在服务器端,对客户端透明。
  • 目标:正向代理旨在隐藏客户端,帮助客户端访问资源;反向代理则是隐藏服务器端详情,提供额外的安全性、性能优化和负载均衡能力。

综上所述,正向代理和反向代理的主要区别在于代理服务的侧重点和部署策略,分别服务于客户端的需求隐藏和服务器端的架构优化及安全增强。

6.Nginx

Nginx概念及工作原理

Nginx 是一款轻量级的 Web 服务器软件,专为高效率和低资源消耗而设计。除了基本的网页服务功能,Nginx 还能作为反向代理服务器、负载均衡器以及实现HTTP缓存策略,广泛应用于构建高性能的现代网络架构。

核心特性

  • 异步事件驱动模型:区别于传统服务器如Apache采用的进程或线程模型,Nginx运用了事件驱动的方式处理请求,这种机制使它能够以更少的资源处理更多的并发连接,显著提升了处理能力与响应速度。

架构层次

Master Process(主进程)

  • 管理与控制:Nginx架构的顶级元素是master process,负责加载配置、监控状态以及维护工作进程的生命周期,但不直接参与请求处理。

Worker Processes(工作进程)

  • 并发处理核心:由主进程创建的worker processes承担了实际的请求处理工作。得益于事件驱动设计,每个worker进程能够同时处理大量HTTP请求,无需为每个请求分配单独的线程或进程,这是Nginx在性能上超越诸如Apache(后者基于每个连接/请求分配独立进程的模型)的关键所在。

工作流程

  1. 请求接收:客户端发起HTTP请求至Nginx服务器。
  2. 请求分发:Nginx可根据配置执行反向代理或负载均衡功能,将请求智能路由到后端服务器。
  3. 高效处理:利用epoll(Linux环境下)等I/O多路复用技术,工作进程异步非阻塞地监听和响应事件,即使面对文件I/O或后端响应等待,也能继续处理其他请求。
  4. 响应与缓存:处理完成后,将响应数据返回客户端;对于静态资源,Nginx可实施缓存策略加速后续相同请求的响应。

综上所述,Nginx凭借其独特的事件驱动架构和高度优化的工作进程模型,在处理高并发场景时展现出卓越的性能,成为众多大型网站和服务的首选基础架构组件。

相关文章:

八、浏览器同源策略

上一篇&#x1f449;: 浏览器垃圾回收机制 文章目录 浏览器同源策略1.同源策略的定义2.同源策略的作用3.同源策略的限制范围4.解决跨域方案汇总1.CORS&#xff08;跨源资源共享&#xff09;2.JSONP3.postMessage 跨域4.Nginx代理跨域5.Node.js中间件代理跨域6.document.domain…...

重载赋值运算符

c编译器可能会给类添加四个函数 1默认构造函数 2默认析构函数 3默认拷贝构造函数&#xff0c;对成员变量进行浅拷贝。 4默认赋值函数&#xff0c;队成员变量进行浅拷贝。 #include<iostream> using namespace std; class CGirl { public:int m_bh;string m_name;voi…...

数字信号处理及MATLAB仿真(2)——离散系统

上回书说到如何来编写一些简单的离散时间序列&#xff0c;今天咱们就来谈谈一些关于常系数差分方程的操作吧。 说到这里咱们对于常系数差分方程可能最关心的就是怎么去求解了。 其中最关键的部分就是filter函数&#xff0c;可以用来计算系统在输入信号为x的输出信号y。大家学过…...

大模型思维链(Chain-of-Thought)技术原理

大模型思维链&#xff08;Chain-of-Thought&#xff09;技术原理 NLP中 大语言模型LLM中的思维链 Chain-of-Thought(CoT) GoT_cot思维链-CSDN博客 https://zhuanlan.zhihu.com/p/680618940 https://zhuanlan.zhihu.com/p/661475269...

gda动态调试-cnblog

忽的发现gda有动态调试功能 动态监听返回值 框柱指定方法&#xff0c;选择调试方法&#xff0c;gda会自动监听函数的返回值&#xff0c;例如 自定义frida脚本 gda会自动生成hook该函数的frida脚本...

Double 4 VR仿真情景实训教学系统在法律专业课堂上的应用

随着科技的飞速发展&#xff0c;VR技术逐渐渗透到各个领域&#xff0c;为教育行业带来了革命性的变化。 VR技术以其独特的沉浸式体验&#xff0c;为法律课堂带来了前所未有的学习体验。通过Double 4 VR仿真情景实训教学系统&#xff0c;学生可以身临其境地进入虚拟的仿真情景中…...

k8s-第一节-minikube

minikube 服务器启动 # 启动集群 minikube start # 启动集群并使用docker驱动 minikube start --driverdocker To make docker the default driver:minikube config set driver docker # 查看节点。kubectl 是一个用来跟 K8S 集群进行交互的命令行工具 kubectl get node # 停…...

html+js+css在线倒计时

代码在图片后面 点赞加关注 谢谢大佬照顾&#x1f61c; 图例 时间到前 时间到后 源代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width,…...

构建LangChain应用程序的示例代码:55、如何实现多代理模拟,其中特权代理决定谁发言。这遵循与多代理分散发言者选择相反的选择方案

示例展示了如何实现一个多代理模拟,其中一个特权代理决定谁来发言。 这遵循与多代理分散式发言人选择相反的选择方案。 我们在一个虚构的新闻网络模拟环境中展示这种方法的一个例子。这个例子将展示我们如何实现能够: 在说话前思考终止对话 的代理。 导入LangChain相关模块…...

船舶雷达与导航系统选择7/8防水插座的原因分析

概述 船舶雷达与导航系统在现代航海中扮演着至关重要的角色&#xff0c;它们为船舶提供准确的导航信息&#xff0c;确保航行的安全和效率。在这些系统中&#xff0c;7/8防水插座的使用尤为重要&#xff0c;因为它们能够在恶劣的海上环境中提供稳定的电力和信号连接。接下来&am…...

墨烯的C语言技术栈-C语言基础-006

六.常量 C语言的常量为 字面常量 const修饰的常变量 #define定义的 枚举常量 int main() { // 四个都是字面常量 30; 3.14; "w"; // 字符常量 "abc"; // const修饰的常变量 const int a 10; // 在C语言中,const修饰的a,本质是变量,但不能直…...

常用SHELL命令

在 Unix/Linux 系统中&#xff0c;除了基本的文件和目录操作命令外&#xff0c;还有许多强大的工具命令&#xff0c;用于文本处理、系统监控、文件操作等。以下是一些常用的 Shell 命令&#xff0c;特别是类似 sed 和 awk 的文本处理工具&#xff1a; 文本处理命令 sed - 流编…...

Python脚本:将Word文档转换为Excel文件

引言 在文档处理中&#xff0c;我们经常需要将Word文档中的内容转换成其他格式&#xff0c;如Excel&#xff0c;以便更好地进行数据分析和报告。针对这一需求&#xff0c;我编写了一个Python脚本&#xff0c;能够批量处理指定目录下的Word文档&#xff0c;将其内容结构化并转换…...

【单链表】03 设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux算法题上机准备 &#x1f618;欢迎 ❤️关注 &#x1f44d;点赞 &#x1f64c;收藏 ✍️留言 题目 设L为带头结点的单链表&#xff0c;编写算法实现从尾到头反向输出每个结点的值。 算法…...

鸿蒙开发设备管理:【@ohos.vibrator (振动)】

振动 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 imp…...

【信息学奥赛】CSP-J/S初赛07 排序算法及其他算法在初赛中的考察

本专栏&#x1f449;CSP-J/S初赛内容主要讲解信息学奥赛的初赛内容&#xff0c;包含计算机基础、初赛常考的C程序和算法以及数据结构&#xff0c;并收集了近年真题以作参考。 如果你想参加信息学奥赛&#xff0c;但之前没有太多C基础&#xff0c;请点击&#x1f449;专栏&#…...

第N7周:seq2seq翻译实战-pytorch复现-小白版

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 理论基础 seq2seq&#xff08;Sequence-to-Sequence&#xff09;模型是一种用于机器翻译、文本摘要等序列转换任务的框架。它由两个主要的递归神经网络&#…...

java集合(1)

目录 一.集合概述 二. 集合体系概述 1. Collection接口 1.1 List接口 1.2 Set接口 2. Map接口 三. ArrayList 1.ArrayList常用方法 2.ArrayList遍历 2.1 for循环 2.2 增强for循环 2.3 迭代器遍历 一.集合概述 我们经常需要存储一些数据类型相同的元素,之前我们学过…...

分布式数据库HBase:从零开始了解列式存储

在接触过大量的传统关系型数据库后你可能会有一些新的问题: 无法整理成表格的海量数据该如何储存? 在数据非常稀疏的情况下也必须将数据存储成关系型数据库吗? 除了关系型数据库我们是否还有别的选择以应对Web2.0时代的海量数据? 如果你也曾经想到过这些问题, 那么HBase将是…...

接口测试流程及测试点!

一、什么时候开展接口测试 1.项目处于开发阶段&#xff0c;前后端联调接口是否请求的通&#xff1f;&#xff08;对应数据库增删改查&#xff09;--开发自测 2.有接口需求文档&#xff0c;开发已完成联调&#xff08;可以转测&#xff09;&#xff0c;功能测试展开之前 3.专…...

已经安装deveco-studio-4.1.3.500的基础上安装deveco-studio-3.1.0.501

目录标题 1、执行exe文件后安装即可2、双击devecostudio64_3.1.0.501.exe2.1、安装Note (注意和4.1的Note放不同目录)2.2、安装ohpm (注意和4.1版本的ohpm放不同目录)2.3、安装SDK (注意和4.1版本的SDK放不同目录) 1、执行exe文件后安装即可 2、双击devecostudio64_3.1.0.501.e…...

【C++】 解决 C++ 语言报错:Use of Uninitialized Variable

文章目录 引言 使用未初始化的变量&#xff08;Use of Uninitialized Variable&#xff09;是 C 编程中常见且危险的错误之一。它通常在程序试图使用尚未赋值的变量时发生&#xff0c;导致程序行为不可预测&#xff0c;可能引发运行时错误、数据损坏&#xff0c;甚至安全漏洞。…...

2024年7月6日 十二生肖 今日运势

小运播报&#xff1a;2024年7月6日&#xff0c;星期六&#xff0c;农历六月初一 &#xff08;甲辰年庚午月辛未日&#xff09;&#xff0c;法定节假日。 红榜生肖&#xff1a;猪、马、兔 需要注意&#xff1a;狗、鼠、牛 喜神方位&#xff1a;西南方 财神方位&#xff1a;正…...

ubuntu丢失网络/网卡的一种原因解决方案

现象 开机进入ubuntu后发现没有网络&#xff0c;无论是在桌面顶部状态栏的快捷键 还是 系统设置中&#xff0c;都没有”有线网“和”无线网“的选项&#xff0c;”代理“的选项是有的使用数据线连接电脑和手机&#xff0c;手机开启”通过usb共享网络“&#xff0c;还是没有任何…...

第6篇 共识机制深度解析:PoW、PoS、DPoS和PBFT

在区块链的世界里,有一个非常重要的概念叫做“共识机制”。它就像是区块链的心脏,保证大家在这条链上的信息是可靠的、不可篡改的。今天,我们就来通俗易懂地聊聊区块链里的四大共识机制:工作量证明(PoW)、权益证明(PoS)、委托权益证明(DPoS)和拜占庭容错(PBFT)。为…...

Windows环境使用SpringBoot整合Minio平替OSS

目录 配置Minio环境 一、下载minio.exe mc.exe 二、设置用户名和密码 用管理员模式打开cmd 三、启动Minio服务器 四、访问WebUI给的地址 SpringBoot整合Minio 一、配置依赖&#xff0c;application.yml 二、代码部分 FileVO MinioConfig MinioUploadService MinioController 三…...

LeetCode 196, 73, 105

目录 196. 删除重复的电子邮箱题目链接表要求知识点思路代码 73. 矩阵置零题目链接标签简单版思路代码 优化版思路代码 105. 从前序与中序遍历序列构造二叉树题目链接标签思路代码 196. 删除重复的电子邮箱 题目链接 196. 删除重复的电子邮箱 表 表Person的字段为id和email…...

在Apache HTTP服务器上配置 TLS加密

安装mod_ssl软件包 [rootlocalhost conf.d]# dnf install mod_ssl -y此时查看监听端口多了一个443端口 自己构造证书 [rootlocalhost conf.d]# cd /etc/pki/tls/certs/ [rootlocalhost certs]# openssl genrsa > jiami.key [rootlocalhost certs]# openssl req -utf8 -n…...

C语言力扣刷题11——打家劫舍1——[线性动态规划]

力扣刷题11——打家劫舍1和2——[线性动态规划] 一、博客声明二、题目描述三、解题思路1、线性动态规划 a、什么是动态规划 2、思路说明 四、解题代码&#xff08;附注释&#xff09; 一、博客声明 找工作逃不过刷题&#xff0c;为了更好的督促自己学习以及理解力扣大佬们的解…...

房屋租赁管理小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;中介管理&#xff0c;房屋信息管理&#xff0c;房屋类型管理&#xff0c;租房订单管理&#xff0c;租房信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;房屋信息&am…...

oracle sql语句 排序 fjd = ‘0101‘ 排在 fjd = ‘0103‘ 的前面

要实现这个排序需求&#xff0c;你可以使用 CASE 表达式来自定义排序逻辑。假设你有一个表格名为 your_table&#xff0c;并且有一个字段 fjd 存储类似 ‘0101’, ‘0103’ 这样的值&#xff0c;你可以这样编写 SQL 查询&#xff1a; SELECT * FROM your_table ORDER BY CASE …...

初试成绩占比百分之70!计算机专硕均分340+!华中师范大学计算机考研考情分析!

华中师范大学&#xff08;Central China Normal University&#xff09;简称“华中师大”或“华大”&#xff0c;位于湖北省会武汉&#xff0c;是中华人民共和国教育部直属重点综合性师范大学&#xff0c;国家“211工程”、“985工程优势学科创新平台”重点建设院校&#xff0c…...

【面向就业的Linux基础】从入门到熟练,探索Linux的秘密(十)-git(2)

下面是一些git的常用命令和基本操作&#xff0c;可以当做平常的笔记查询&#xff0c;用于学习&#xff01;&#xff01;&#xff01; 文章目录 前言 一、git 二、git常用命令 总结 前言 下面是一些git的常用命令和基本操作&#xff0c;可以当做平常的笔记查询&#xff0c;用于…...

JMH320【亲测】【御剑九歌】唯美仙侠手游御剑九歌+WIN学习手工端+视频教程+开服清档+运营后台+授权GM物品充值后台

资源介绍&#xff1a; 这也是仙梦奇缘的一个游戏 注意&#xff1a;外网14位IP或域名 ———————————————————————————————————– ps后台介绍: 1区运营后台&#xff1a;http://ip:9981/admin/admintool/ 2区运营后台&#xff1a;http://ip…...

【matlab】信号分解/故障诊断——智能优化算法优化VMD

目录 引言 应用领域 VMD代码实现 智能优化算法优化VMD 引言 VMD&#xff08;变分模态分解&#xff09;是一种新的非线性自适应信号分解方法&#xff0c;它通过变分原理将复杂信号分解为若干个具有不同频率中心和带宽的本征模态函数&#xff08;Intrinsic Mode Functions, …...

【重磅】万能模型-直接能换迪丽热巴的模型

万能模型&#xff0c;顾名思义&#xff0c;不用重新训练src&#xff0c;直接可以用的模型&#xff0c;适应大部分原视频脸 模型用法和正常模型一样&#xff0c;但可以跳过训练阶段&#xff01;直接到合成阶段使用该模型 本模型没有做Xseg&#xff0c;对遮挡过多的画面不会自动适…...

Web基础和HTTP协议

web基础与HTTP协议: web:就是我们所说的网页。打开网站展示的页面。(全球广域网&#xff0c;万维网) world wide web 分布式图形信息系统 http https 超文本传输协议 分布式:计算机系统或者应用程序分布在多台计算机或者服务器上。通过计算机网络互相通信和协作。共同完成任…...

Mini-L-CTF-2022 minispringboot Thymeleaf模板注入 spel的绕过

Mini-L-CTF-2022 minispringboot Thymeleaf模板注入 spel的绕过 就是一个低版本的Thymeleaf注入 漏洞点 public class MainController {GetMapping({"/{language}"})public String test(PathVariable(name "language") String language, RequestParam(…...

LLM - 神经网络的组成

1. 一个神经元的结构&#xff1a;即接受多个输入X向量&#xff0c;在一个权重向量W和一个偏执标量b的作用下&#xff0c;经过激活函数后&#xff0c;产生一个输出。 2. 一层神经网络的结构&#xff1a;该层网络里的每个神经元并行计算&#xff0c;得到各自的输出;计算方式是输入…...

C++:拷贝构造函数

拷贝构造函数的引入 用对象来初始化对象 (1)简单变量定义时&#xff0c;可以直接初始化&#xff0c;也可以用另一个同类型变量来初始化。举例说明 (2)用class来定义对象时&#xff0c;可以直接初始化&#xff0c;也可以用另一个对象来初始化。举例说明 testperson xiaohong(na…...

云服务出现故障这样处理

无法连接云服务器 服务器远程无法连接时&#xff0c;可通过7ECloud控制台进行连接。 常见故障现象 1、ping不通 2、ping丢包 3、部分端口telnet不通 4、全部端口telnet不通 5、广告、弹窗植入 6、域名无法访问IP访问正常 常见故障原因 1、云服务器过期、关机或者EIP被…...

CVPR2024自动驾驶轨迹预测方向的论文整理

2024年自动驾驶轨迹预测方向的论文汇总 1、Producing and Leveraging Online Map Uncertainty in Trajectory Prediction 论文地址&#xff1a;https://arxiv.org/pdf/2403.16439 提出针对在线地图不确定性带给轨迹预测的影响对应的解决方案。 在轨迹预测中&#xff0c;利用在…...

数据结构——队列练习题

在C语言中&#xff0c;.和->运算符用于访问结构体的成员变量。它们之间的区别在于&#xff1a;.运算符用于访问结构体变量的成员。->运算符用于访问结构体指针变量的成员 1a&#xff08;rear指向队尾元素后一位&#xff0c;判空判满时牺牲一个存储单元&#xff09; 首先…...

PLL和CDR的内部结构及其区别

比较PLL和CDR的内部结构及其区别&#xff1a; 基本结构&#xff1a; PLL&#xff08;相位锁定环&#xff09;&#xff1a; 相位检测器环路滤波器压控振荡器&#xff08;VCO&#xff09;分频器&#xff08;可选&#xff0c;用于频率合成&#xff09; CDR&#xff08;时钟数据恢复…...

HarmonyOS APP应用开发项目- MCA助手(Day02持续更新中~)

简言&#xff1a; gitee地址&#xff1a;https://gitee.com/whltaoin_admin/money-controller-app.git端云一体化开发在线文档&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agc-harmonyos-clouddev-view-0000001700053733-V5注&#xff1a;…...

华为交换机 LACP协议

华为交换机支持的LACP协议&#xff0c;即链路聚合控制协议&#xff0c;是一种基于IEEE 802.3ad标准的动态链路聚合与解聚合的协议。它允许设备根据自身配置自动形成聚合链路并启动聚合链路收发数据。 在LACP模式下&#xff0c;链路聚合组能够自动调整链路聚合&#xff0c;维护…...

node 下载文件到网络共享目录

1、登录网络共享计算器 2、登录进入后复制要存储文件的目录路径 例如&#xff1a; \\WIN-desktop\aa\bb\cc 3、node 下载后写入网络共享目录 注意&#xff08;重要&#xff09;:在使用UNC路径时&#xff0c;请确保你正确转义了反斜杠&#xff08;使用两个反斜杠来表示一个&…...

STM32基础知识

一.STM32概述 第一款STM32单片机发布的时间为2007年6月11日。由意法半导体&#xff08;ST&#xff09;公司推出&#xff0c;是STM32系列中的首款产品&#xff0c;具体型号为STM32F1&#xff0c;它是一款基于Cortex-M内核的32位微控制器&#xff08;MCU&#xff09;。 STM32F1…...

安装docker版rabbitmq 3.12

本文介绍在Ubuntu22中安装docker版rabbitmq 3.12。 一、拉取镜像 docker pull rabbitmq:3.12.14-management二、创建数据目录和docker-compose文件 创建目录&#xff1a; cd /root mkdir rabbitmq-docker cd rabbitmq-docker mkdir data chmod 777 data创建docker-compose配…...

c++重定向输出和输出(竞赛讲解)

1.命令行重定向 在命令行中指定输出文件 指令 .\重定向学习.exe > 1.txt 效果 命令行输入和输出 指令 .\重定向学习.exe < 2.txt > 1.txt 效果 代码 #include<bits/stdc++.h> using namespace std; int n; int main(){cin>>n;for(int i=0;i<n;i…...