Skip to content

跨域、跨站与浏览器安全策略

1 跨域

协议域名端口,三者有一不一样,就是跨域 案例一:www.baidu.com 与 zhidao.baidu.com 是跨域 目前有三种最常见的解决方案:

  1. CORS,在服务器端设置几个响应头,如 Access-Control-Allow-Origin: *
  2. 反向代理服务器:Reverse Proxy,在 nginx/traefik/haproxy 等反向代理服务器中设置为同一域名。前端向后端发送请求时会先经过代理服务器,代理服务器再向后端发送请求,后端反回数据给前端,前端本身是不知道的,也就是反向代理服务器对于前端是透明的。
  3. JSONP

反向代理详解

Reverse Proxy是一种位于客户端和实际服务器之间的服务器,它接收客户端的请求,然后将这些请求转发给后端服务器,并将后端服务器的响应返回给客户端。客户端并不知道它正在与反向代理通信,而认为是在直接与目标服务器通信。

客户端 → 反向代理 → 后端服务器
客户端 ← 反向代理 ← 后端服务器
主要功能与用途
  1. 负载均衡
nginx
# Nginx 配置示例
upstream backend {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=2;
    server 192.168.1.12:8080 weight=1;
}

server {
    location / {
        proxy_pass http://backend;
    }
}
  1. 缓存加速
  • 缓存静态资源(图片、CSS、JS等)
  • 减少后端服务器压力
  • 提高响应速度
  1. 安全防护
  • 隐藏后端服务器真实IP
  • 提供SSL/TLS终止
  • 防御DDoS攻击
  • Web应用防火墙(WAF)
  1. SSL终端
nginx
server {
    listen 443 ssl;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://backend_server;
        proxy_set_header Host $host;
    }
}
  1. 内容压缩
nginx
gzip on;
gzip_types text/plain text/css application/json;
  1. 统一入口点
  • 多个服务使用同一域名和端口
  • 基于路径或域名的路由
常见反向代理软件
  1. Nginx
nginx
server {
    listen 80;
    server_name example.com;
    
    location /api/ {
        proxy_pass http://api_backend;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    location /static/ {
        proxy_pass http://static_backend;
        expires 30d;
    }
}
  1. Apache
apache
<VirtualHost *:80>
    ProxyPreserveHost On
    ProxyPass /api http://backend-api:8080/
    ProxyPassReverse /api http://backend-api:8080/
</VirtualHost>
  1. HAProxy
haproxy
frontend web_front
    bind *:80
    default_backend web_servers

backend web_servers
    balance roundrobin
    server web1 192.168.1.10:80 check
    server web2 192.168.1.11:80 check
反向代理 vs 正向代理
特性反向代理正向代理
位置服务器端客户端
服务对象后端服务器客户端
客户端感知不知道代理存在知道代理存在
主要用途负载均衡、安全、缓存访问控制、翻墙、缓存
实际应用场景
  1. 微服务架构
客户端 → API网关(反向代理) → [用户服务, 订单服务, 支付服务]
  1. CDN(内容分发网络)
nginx
# CDN边缘节点配置
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    proxy_cache my_cache;
    proxy_pass http://origin_server;
    expires 1y;
}

2 跨站

顶级域名和二级域名不同 Pasted image 20250903180758.png

3 浏览器安全策略

浏览器中的安全,可以按照系统安全、网络安全、页面安全三个方面来了解。

谁也无法保证浏览器自身不存在漏洞,浏览器在执行前又无法分辨从网络拿到的资源是否安全,而操作系统的各种权限让网络资源接触到是有风险的,因此默认所有网络资源都是不可信的。

现代浏览器早已经拥抱了多进程的架构,从输入 url 到页面展示,浏览器中多个进程通力合作,让用户看到一个期望的图像,其中最重要的一个进程,渲染进程,是执行网络资源的关键进程,因此浏览器通过安全沙箱,把渲染进程包了起来。

安全沙箱

安全沙箱最小的保护单位是进程,安全沙箱会限制进程对操作系统资源的访问/修改。

需要注意的是,tab 和渲染进程并不是一对一的关系:

同一站点的意思是,协议和根域名相同,与同源相比,判断条件宽松许多;而连接关系的意思是,b 页面是在 a 页面中通过 window.open ——此时可以在 a 中使用 window.open 的返回控制 b 页面;或者 a target="_blank" ——此时可以在 b 中通过 window.opener 控制 a ——的方式打开的。

网络安全(SSL与TLS)

http 生来为传输 html ,但随着 web 的发展,http 的功能越来越不够用,伴随着功能上的完善,网络安全问题也成为重要研究对象。

http 的风险有三点:

  • 窃听风险:第三方可以获知通信内容
  • 篡改风险:第三方可以修改通信内容
  • 冒充风险:第三方可以冒充他人身份参与通信

为此, TCP 和 HTTP 之间被插入一个安全层,所有经过的数据会被加密/解密。

接入了安全层的 http 变成了 https ,它的特点有:

  • 所有信息都是加密传播,第三方无法窃听。
  • 具有校验机制,一旦被篡改,通信双方会立刻发现。
  • 配备身份证书,防止身份被冒充。
https 加密过程

一个重要的规则是,公钥加密的数据只有私钥能解密。

公钥是明文的,黑客容易破解,但私钥只有服务器有,而 pre-master 是公钥加密生成的,因此只有服务器能破解。最终的 master secret 有了 pre-master 的参与,数据发送和接受了都很安全。

而且,只需要进行一次非对称加密就可以了,传输效率也比较高。

当然,黑客服务器自己生产公钥私钥,客户端可能进入假的页面。服务器怎么证明自己是真实合法的呢?数字证书。

CA 证书

CA是一个机构,它的职责是给一些公司或者个人颁发数字证书。

数字证书需要申请,流程如下:

CA 审核是线上线下结合的,很多时候线下审核依赖本地政策,于是现实中需要分级治理,进而形成了一个 CA 链。浏览器验证的时候会沿着 CA 链向上寻找,直到根 CA:

即便黑客伪造了服务器,但是由于证书是没有办法伪造的,无法欺骗用户。

页面安全

页面经过 https 请求资源、安全沙箱渲染出来,执行脚本时,可能会有一些恶意脚本被执行;或者,用户受到诱惑,点击了一些通往恶意站点的链接时,可能出现什么情况呢?

  • DOM、CSSOM 被修改
  • 用户行为受到监听
  • 敏感信息遭到劫持
  • Cookie、indexDB 等数据被读取、上传、使用
  • 用户请求被伪造

没有安全保障的 web 世界很可怕,无序、充满陷阱。而页面中最基础、最核心的安全策略是什么?

同源策略( Same-origin policy )。

不同源的 js 脚本无法读写当前页面的 DOM;不同源的 js 脚本无法读取当前页面的 Cookie、IndexDB、LocalStorage 等;不同源的 XMLHttpRequest 访问无法进行。

这样一来,很多正常的事情也变得不太方便了,比如 cdn 资源请求。因此为了一些便利性,同源策略给第三方资源发了通行证,这样一来,安全问题产生了。

典型的安全攻击有:XSS (Cross-site script) 和 CSRF (Cross-site request forgery,跨站请求伪造)。

顾名思义,前者以插入脚本读取敏感为主,后者则非法使用 cookie 伪造用户请求达到不可告人的目的。

XSS 跨站脚本攻击

Server对用户输入的数据没有进行严格的过滤,导致出现了意外的脚本语句被执行。主要就是通过URL与输入框来进行脚本的注入。 三种常用的 XSS 攻击方法:

  • 存储型,利用内容管理系统的漏洞,比如评论,编辑文章,向服务器发送了恶意代码,将恶意代码存储在Server中,其他的用户加载这些存有恶意代码的评论、文章就会受到攻击:

  • 反射型,与存储型 xss 攻击不同的是,服务器不存储恶意代码,服务端会将恶意代码再次传回前端,这时恶意代码就会存在于用户的界面中,有可能会被执行:

Pasted image 20251214215853.png

  • 基于 DOM 的攻击,和反射型很像,但仅在前端运行,并不会提交到后端再返回来:
阻止 XSS 攻击
  • 服务器对输入的脚本进行过滤/转码
  • 使用 CSP (内容安全策略)让服务器决定浏览器可以加载哪些资源,执行哪些脚本。
CSRF 跨站请求伪造攻击

CSRF 攻击利用用户的登录状态和服务器的漏洞。通过链接或者其他方式,伪装成用户请求信息来发送请求到服务器,这样就可以顶替用户的信息来修改或者破坏网站,比如自动转发邮件,转账等等,但是有两个前提: 1、服务端有漏洞; 2、用户要点击黑客页面的链接。

如何防止 CSRF 攻击呢?

我们需要提升服务器的安全性。

  • 从第三方站点发送请求时,禁止发送 Cookie —— set-cookie 中设置 SameSite 为 Strict
  • 验证请求的来源站点 —— 通过 Request Header: Referer || Origin
  • CSRF Token 验证,服务器要求所有请求必须携带 CSRF Token ,第三方无法拿到 Token ,伪造的请求会被拒绝访问
SSRF 服务端请求伪造攻击

Server对于用户所提供的URL过于信任,没有对攻击者的URL进行限制,这个URL能访问到内部的Server,以此为跳板,就可能会导致内网中的Server被攻击到

  • 使用黑名单,禁止用户访问某些内部地址
  • 使用白名单