【iframe 跨域问题:代理方案与网络基础】

iframe 跨域问题:代理方案与网络基础

文档概述

本文档基于实际项目经验,讲解 iframe 跨域问题的根本原因、代理解决方案(Vite/Nginx)、Cookie 携带配置,以及必要的网络基础知识(NAT、公网/内网等)。

适用场景

  • 新旧系统集成(通过 iframe 嵌入旧系统)
  • 跨域资源访问
  • 多环境部署配置(本地开发、测试、生产)
  • 内网与公网混合架构

技术栈

  • 前端:Vue 3 + Vite
  • 服务器:Nginx
  • 部署:阿里云 ECS

第一章:问题现象与分析

1.1 问题描述

在开发过程中遇到以下问题场景:

场景:新系统(Vue3 前端)需要通过 iframe 嵌入旧系统页面

问题现象

  1. 直接访问旧系统地址:http://192.168.1.100:8080/app/page
  2. iframe 页面加载后,旧系统内部的 AJAX 请求报错
  3. 第一个登录接口成功,第二个业务接口报跨域错误
  4. 浏览器提示:"此连接已被阻止,因为它是公共页面发起的,旨在连接到您本地网络上的设备或服务器"

1.2 错误信息分析

跨域错误(CORS Error)
复制代码
Access to XMLHttpRequest at 'http://192.168.1.100:8080/api/xxx'
from origin 'http://localhost:5173' has been blocked by CORS policy

原因:浏览器的同源策略(Same-Origin Policy)限制

Private Network Access 错误
复制代码
此连接已被阻止,因为它是公共页面发起的,
旨在连接到您本地网络上的设备或服务器

原因:Chrome 浏览器的 Private Network Access (PNA) 策略,防止公网页面访问本地/内网资源

1.3 问题根本原因

同源策略限制

浏览器判断两个 URL 是否同源的标准:

要素 说明
协议 http vs https
域名 localhost vs 192.168.1.100
端口 5173 vs 8080

三者必须完全相同才算同源

示例:

复制代码
父页面:http://localhost:5173/test/old-system-iframe
iframe:http://192.168.1.100:8080/app/page
                ↑                    ↑
            域名不同              端口不同

结论:不同源 → 跨域限制

即使后端配置了 CORS 响应头,Cookie 仍然可能无法携带:

复制代码
第一次请求(登录):
  → 后端返回 Set-Cookie: sessionId=xxx; SameSite=Lax
  → 浏览器保存 Cookie

第二次请求(业务接口):
  → 浏览器发现是跨域请求
  → SameSite=Lax 不允许跨域携带 Cookie
  → 请求不带 Cookie → 后端认为未登录 → 403/401

第二章:浏览器安全策略详解

2.1 跨域资源共享(CORS)

CORS 基本原理
复制代码
浏览器发起跨域请求
    ↓
1. 简单请求:直接发送,检查响应头
2. 预检请求:先发 OPTIONS,通过后再发实际请求
    ↓
服务器返回响应头
    ↓
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
    ↓
浏览器检查响应头
    ↓
符合 → 允许访问
不符合 → 阻止,报 CORS 错误
CORS 配置示例

后端配置(Java/Spring Boot)

java 复制代码
@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        // 允许所有来源(生产环境应指定具体域名)
        config.addAllowedOriginPattern("*");
        // 允许所有HTTP方法
        config.addAllowedMethod("*");
        // 允许所有请求头
        config.addAllowedHeader("*");
        // 允许携带Cookie
        config.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

后端配置(Node.js/Express)

javascript 复制代码
const cors = require('cors')

app.use(
  cors({
    origin: '*', // 生产环境应指定具体域名
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    allowedHeaders: ['Content-Type', 'Authorization'],
  }),
)
SameSite 属性说明
说明 跨域携带 安全性
Strict 完全禁止跨站发送 ❌ 否 最高
Lax 部分允许(默认值) ⚠️ 仅顶级导航 中等
None 允许跨站发送 ✅ 是(需配合Secure) 较低
SameSite=Lax 的限制

默认情况下,浏览器设置 Cookie 时使用 SameSite=Lax

复制代码
场景1:用户点击链接
  <a href="https://other-site.com">链接</a>
  → Cookie 会携带 ✅

场景2:iframe 嵌入
  <iframe src="https://other-site.com"></iframe>
  → Cookie 不会携带 ❌

场景3:AJAX 请求
  fetch('https://other-site.com/api')
  → Cookie 不会携带 ❌
SameSite=None 的要求

要允许 iframe 或 AJAX 跨域携带 Cookie,必须:

复制代码
Set-Cookie: sessionId=xxx; SameSite=None; Secure
                            ↑             ↑
                      允许跨域        必须HTTPS

注意SameSite=None 必须配合 Secure 属性,意味着必须在 HTTPS 环境下使用。

浏览器兼容性
复制代码
Chrome 80+ (2020年2月):默认 SameSite=Lax
Firefox 69+ (2019年9月):默认 SameSite=Lax
Safari:更严格,完全阻止第三方Cookie
Edge:跟随 Chrome

2.3 Private Network Access (PNA) 策略

PNA 策略目的

防止公网页面攻击内网设备:

复制代码
恶意网站(公网)
    ↓ 想访问
用户的路由器管理页面(192.168.1.1)
用户的打印机(192.168.1.100)
用户的 NAS(192.168.1.200)
    ↓
PNA 策略阻止 ❌
触发条件
复制代码
条件1:页面来源是公网地址
条件2:请求目标是私有网络地址(10.x, 172.16-31.x, 192.168.x)
条件3:没有正确的 CORS 响应头
    ↓
浏览器阻止请求
解决方案

后端添加响应头:

复制代码
Access-Control-Allow-Private-Network: true

配合标准的 CORS 响应头一起使用。


第三章:代理方案详解

3.1 代理的本质

什么是代理

代理本质上是"请求转发":

复制代码
客户端 → 发送请求到代理服务器 → 代理转发到目标服务器
        ↑                          ↑
     同源(无跨域)              可能跨域,但服务器之间无限制
                                    ↓
                                返回响应
                                    ↓
客户端 ← 代理返回响应

关键点

  1. 浏览器只看到与代理服务器的交互(同源)
  2. 代理服务器与目标服务器的交互不受浏览器限制
  3. Cookie 会自动携带(因为浏览器认为是同源)
代理 vs CORS
方案 原理 优点 缺点
CORS 后端添加响应头 直接访问,性能好 Cookie携带复杂,浏览器限制多
代理 请求转发 彻底解决跨域,Cookie自动携带 多一层转发,配置相对复杂

3.2 Vite 代理配置(开发环境)

基本配置
typescript 复制代码
// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  server: {
    host: '0.0.0.0',
    port: 5173,
    proxy: {
      // 代理旧系统
      '/old-system': {
        target: 'http://192.168.1.100:8080',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/old-system/, ''),
      },
    },
  },
})
配置详解
typescript 复制代码
'/old-system': {
  // 目标服务器地址
  target: 'http://192.168.1.100:8080',

  // 改变请求头中的 origin 为目标地址
  changeOrigin: true,

  // 路径重写:/old-system/api → /api
  rewrite: (path) => path.replace(/^\/old-system/, ''),

  // 代理日志(调试用)
  configure: (proxy) => {
    proxy.on('proxyReq', (proxyReq, req) => {
      console.log('[Proxy]', req.method, req.url, '→', proxyReq.path)
    })
    proxy.on('error', (err) => {
      console.error('[Proxy Error]', err)
    })
  }
}
请求流程
复制代码
浏览器发起请求
  ↓
http://localhost:5173/old-system/app/page
  ↓ Vite 拦截 /old-system 开头的请求
  ↓ 转发到目标服务器
http://192.168.1.100:8080/app/page
  ↓ 目标服务器返回响应
  ↓ Vite 转发回浏览器
浏览器收到响应

对浏览器而言

  • 请求地址:http://localhost:5173/old-system/...
  • 完全同源,无跨域限制
  • Cookie 自动携带

如果后端 Cookie 的 SameSite 设置不当,可以在代理层重写:

typescript 复制代码
'/old-system': {
  target: 'http://192.168.1.100:8080',
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/old-system/, ''),
  configure: (proxy) => {
    // 修改响应的 Set-Cookie 头
    proxy.on('proxyRes', (proxyRes) => {
      const setCookieHeaders = proxyRes.headers['set-cookie']
      if (setCookieHeaders) {
        proxyRes.headers['set-cookie'] = setCookieHeaders.map((cookie) => {
          // 将 SameSite=Lax 替换为 SameSite=None
          let modified = cookie.replace(/SameSite=Lax/gi, 'SameSite=None')
          // 添加 SameSite=None
          if (!modified.includes('SameSite')) {
            modified += '; SameSite=None'
          }
          // SameSite=None 必须配合 Secure
          if (!modified.includes('Secure')) {
            modified += '; Secure'
          }
          return modified
        })
      }
    })
  }
}

注意:修改 SameSite 会降低 CSRF 防护,仅在开发环境或内部系统使用。

3.3 Nginx 代理配置(测试/生产环境)

基本配置
nginx 复制代码
server {
    listen 8082;
    server_name _;

    # 前端静态文件
    root /opt/soft/app-client;
    index index.html;

    # 代理后端 API
    location /api/ {
        proxy_pass http://203.0.113.10:8081/;
        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 Cookie $http_cookie;
        proxy_http_version 1.1;
    }

    # 代理旧系统(解决 iframe 跨域)
    location /old-system/ {
        proxy_pass http://192.168.1.100:8080/;
        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 Cookie $http_cookie;
        proxy_http_version 1.1;

        # Cookie 处理(可选)
        # proxy_cookie_domain 192.168.1.100 $host;
        # proxy_cookie_path / /old-system/;
    }

    # Vue Router history 模式支持
    location / {
        try_files $uri $uri/ /index.html;
    }
}
配置说明
nginx 复制代码
location /old-system/ {
    # 目标服务器地址(注意末尾的 /)
    proxy_pass http://192.168.1.100:8080/;

    # 传递原始 Host 头(重要)
    proxy_set_header Host $host;

    # 传递客户端真实 IP
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # 传递 Cookie(重要)
    proxy_set_header Cookie $http_cookie;

    # 使用 HTTP/1.1(支持 keep-alive)
    proxy_http_version 1.1;
}

如果后端设置的 Cookie 带有 Domain 属性,需要重写:

nginx 复制代码
location /old-system/ {
    proxy_pass http://192.168.1.100:8080/;

    # 重写 Cookie 的 Domain
    # 将后端的 Domain 改为当前域名
    proxy_cookie_domain 192.168.1.100 $host;

    # 重写 Cookie 的 Path
    # 将后端的 Path=/ 改为 Path=/old-system/
    proxy_cookie_path / /old-system/;
}
配置生效
bash 复制代码
# 测试配置是否正确
nginx -t

# 重新加载配置(不中断服务)
nginx -s reload

# 重启 Nginx(会中断服务)
systemctl restart nginx

3.4 前端代码配置

iframe 使用代理路径
vue 复制代码
<!-- src/views/test/OldSystemIframe.vue -->
<template>
  <div class="old-system-iframe">
    <div class="iframe-wrapper">
      <!-- 使用代理路径,不是直接地址 -->
      <iframe src="/old-system/app/page" frameborder="0" title="旧系统" />
    </div>
  </div>
</template>

<style scoped>
.old-system-iframe {
  width: 100%;
  height: 100%;
}

.iframe-wrapper {
  width: 100%;
  height: 100%;
}

iframe {
  width: 100%;
  height: 100%;
  border: none;
}
</style>
动态切换环境

如果需要在不同环境使用不同地址:

typescript 复制代码
// src/config/env.ts
export const OLD_SYSTEM_BASE_URL = import.meta.env.VITE_OLD_SYSTEM_BASE_URL || '/old-system'

// .env.development
VITE_OLD_SYSTEM_BASE_URL=/old-system

// .env.production
VITE_OLD_SYSTEM_BASE_URL=/old-system
vue 复制代码
<script setup lang="ts">
import { OLD_SYSTEM_BASE_URL } from '@/config/env'

const iframeSrc = `${OLD_SYSTEM_BASE_URL}/app/page`
</script>

<template>
  <iframe :src="iframeSrc" />
</template>

第四章:网络架构基础

4.1 公网 IP vs 内网 IP

IP 地址分类

公网 IP(Public IP)

  • 全球唯一的地址
  • 可以在互联网上直接访问
  • 示例:203.0.113.108.8.8.8

内网 IP(Private IP)

  • 仅在局域网内有效
  • 不能在互联网上直接访问
  • 可以重复使用(不同局域网可以有相同的内网IP)
私有 IP 地址段(RFC 1918)
复制代码
A 类:10.0.0.0      - 10.255.255.255      (16,777,216 个地址)
B 类:172.16.0.0    - 172.31.255.255      (1,048,576 个地址)
C 类:192.168.0.0   - 192.168.255.255     (65,536 个地址)

判断示例

复制代码
203.0.113.10     → 公网 IP ✅
192.168.1.100    → 内网 IP(C类)
172.16.0.10   → 内网 IP(B类,阿里云内网)
10.0.1.100       → 内网 IP(A类)
8.8.8.8          → 公网 IP(Google DNS)
为什么需要内网 IP
复制代码
IPv4 地址总数:2^32 = 4,294,967,296 个(约 43 亿)

全球设备数量:远超 43 亿

解决方案:
  └─ NAT(网络地址转换)
      └─ 一个公网 IP + 多个内网 IP
          └─ 节省公网 IP 资源

4.2 NAT(网络地址转换)原理

NAT 工作流程
复制代码
内网设备发起请求
    ↓
【内网设备】192.168.1.100:50000
    ↓ 发送请求到 8.8.8.8:53
    ↓
【路由器/网关】
    ↓ NAT 转换
    ├─ 源地址:192.168.1.100:50000 → 公网IP:12345
    ├─ 目标地址:8.8.8.8:53(不变)
    ├─ 记录映射:公网IP:12345 ←→ 192.168.1.100:50000
    ↓
【公网】请求从 公网IP:12345 发出
    ↓
【目标服务器】8.8.8.8:53 收到请求
    ↓ 返回响应到 公网IP:12345
    ↓
【路由器/网关】
    ↓ 根据映射表查找
    ├─ 公网IP:12345 → 对应 → 192.168.1.100:50000
    ↓ 转换后转发
    ↓
【内网设备】192.168.1.100:50000 收到响应
NAT 映射表示例
内网地址 内网端口 公网端口 目标地址 目标端口 状态
192.168.1.100 50000 12345 8.8.8.8 53 活跃
192.168.1.101 51234 12346 1.1.1.1 443 活跃
192.168.1.100 50001 12347 203.0.113.10 80 活跃
内网 → 公网 ✅(可以)
复制代码
内网主动发起连接
    ↓
NAT 记录映射
    ↓
公网响应
    ↓
NAT 根据映射转发回内网
    ↓
✅ 成功通信

关键:内网主动发起,NAT 知道怎么转发回复

公网 → 内网 ❌(不可以)
复制代码
公网主动发起连接
    ↓
NAT 收到请求
    ↓
问题:没有映射记录,不知道转发给哪台内网设备
    ↓
❌ 丢弃请求 或 拒绝连接

关键:没有预先建立的连接,NAT 不知道怎么转发

4.3 内网穿透方案

如果确实需要公网访问内网,有以下方案:

方案1:端口映射(Port Forwarding)

在路由器上配置:

复制代码
配置项:
  外部端口:8080
  内部 IP:192.168.1.100
  内部端口:8080
  协议:TCP

效果:
  公网IP:8080 → 自动转发到 → 192.168.1.100:8080

优点

  • 简单直接
  • 性能好(直接转发)

缺点

  • 需要路由器配置权限
  • 暴露端口有安全风险
  • 每个服务都要单独配置
方案2:内网穿透工具(frp/ngrok)

原理

复制代码
【内网机器】
    ↓ 主动连接并保持
【公网服务器(frp server)】
    ↑ 长连接保持
    ↓ 接收外部请求
【外部访问者】
    ↓ 访问 public.example.com
【frp server】
    ↓ 通过已建立的连接转发
【内网机器】处理请求并返回

frp 配置示例

服务端(公网服务器):

ini 复制代码
# frps.ini
[common]
bind_port = 7000

客户端(内网机器):

ini 复制代码
# frpc.ini
[common]
server_addr = 公网服务器IP
server_port = 7000

[old-system]
type = http
local_ip = 127.0.0.1
local_port = 8080
custom_domains = old-system.example.com

优点

  • 无需路由器配置
  • 支持多种协议
  • 可以添加认证

缺点

  • 需要额外的服务器
  • 性能有一定损耗
  • 依赖第三方服务
方案3:VPN
复制代码
【公网机器】
    ↓ 连接 VPN
【VPN 服务器】
    ↓ 虚拟分配内网 IP
【公网机器】获得虚拟内网 IP(如 10.0.0.100)
    ↓ 现在可以访问内网资源
【内网机器】192.168.1.100

优点

  • 可以访问整个内网
  • 安全性高(加密)
  • 适合多种场景

缺点

  • 需要 VPN 服务器
  • 配置相对复杂
  • 客户端需要安装 VPN 软件

第五章:多环境配置实践

5.1 环境划分

典型的三环境架构:

环境 用途 网络环境 配置
开发环境 本地开发调试 办公室局域网 Vite 代理
测试环境 功能测试、集成测试 云服务器(公网) Nginx 代理
生产环境 正式服务 云服务器(公网) Nginx 代理 + HTTPS

5.2 开发环境配置

目录结构
复制代码
project/
├── vite.config.ts          # Vite 配置
├── .env.development        # 开发环境变量
├── .env.production         # 生产环境变量
└── src/
    ├── config/
    │   └── env.ts          # 环境配置
    └── views/
        └── test/
            └── OldSystemIframe.vue
vite.config.ts
typescript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'

export default defineConfig({
  plugins: [vue()],

  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },

  server: {
    host: '0.0.0.0',
    port: 5173,
    cors: true,

    proxy: {
      // 代理新系统后端 API
      '/api': {
        target: 'http://192.168.1.100:8083', // 局域网后端
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },

      // 代理旧系统(解决跨域和 Cookie 问题)
      '/old-system': {
        target: 'http://192.168.1.100:8080',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/old-system/, ''),

        configure: (proxy) => {
          // 请求日志
          proxy.on('proxyReq', (proxyReq, req) => {
            console.log('[Old System Proxy]', req.method, req.url, '→', proxyReq.path)
          })

          // 修改响应的 Set-Cookie(开发环境)
          proxy.on('proxyRes', (proxyRes) => {
            const setCookieHeaders = proxyRes.headers['set-cookie']
            if (setCookieHeaders) {
              proxyRes.headers['set-cookie'] = setCookieHeaders.map((cookie) => {
                let modified = cookie.replace(/SameSite=Lax/gi, 'SameSite=None')
                if (!modified.includes('SameSite')) {
                  modified += '; SameSite=None'
                }
                if (!modified.includes('Secure')) {
                  modified += '; Secure'
                }
                return modified
              })
            }
          })

          // 错误处理
          proxy.on('error', (err) => {
            console.error('[Old System Proxy Error]', err)
          })
        },
      },
    },
  },
})
环境变量
bash 复制代码
# .env.development
VITE_APP_TITLE=App系统(开发)
VITE_API_BASE_URL=/api
VITE_OLD_SYSTEM_BASE_URL=/old-system
bash 复制代码
# .env.production
VITE_APP_TITLE=App系统
VITE_API_BASE_URL=/api
VITE_OLD_SYSTEM_BASE_URL=/old-system

5.3 测试环境配置

Nginx 配置
nginx 复制代码
# /opt/soft/nginx/conf/nginx.conf

server {
    listen 8082;
    server_name test.example.com;

    # 前端静态文件
    root /opt/soft/app-client;
    index index.html;

    # 代理新系统后端 API
    location /api/ {
        proxy_pass http://203.0.113.10:8081/;
        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 Cookie $http_cookie;
        proxy_http_version 1.1;
    }

    # 代理旧系统(需要确保测试服务器能访问)
    location /old-system/ {
        # 注意:这里的地址必须是测试服务器能访问的
        # 如果是内网地址,需要确保在同一网络
        # 或者改为旧系统的测试环境地址
        proxy_pass http://旧系统测试地址:8080/;
        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 Cookie $http_cookie;
        proxy_http_version 1.1;

        # Cookie 处理
        proxy_cookie_domain 旧系统域名 $host;
    }

    # Vue Router history 模式支持
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 7d;
        add_header Cache-Control "public, immutable";
    }
}
部署脚本
bash 复制代码
#!/bin/bash
# deploy-test.sh

echo "开始部署测试环境..."

# 1. 构建前端
echo "1. 构建前端..."
npm run build

# 2. 备份旧文件
echo "2. 备份旧文件..."
ssh root@203.0.113.10 "cd /opt/soft && cp -r app-client app-client.backup.$(date +%Y%m%d%H%M%S)"

# 3. 上传新文件
echo "3. 上传新文件..."
scp -r dist/* root@203.0.113.10:/opt/soft/app-client/

# 4. 重启 Nginx
echo "4. 重新加载 Nginx..."
ssh root@203.0.113.10 "nginx -t && nginx -s reload"

echo "部署完成!"
echo "访问地址:http://203.0.113.10:8082"

5.4 生产环境配置

Nginx 配置(HTTPS)
nginx 复制代码
# 生产环境配置

# HTTP 重定向到 HTTPS
server {
    listen 80;
    server_name prod.example.com;
    return 301 https://$server_name$request_uri;
}

# HTTPS 配置
server {
    listen 443 ssl http2;
    server_name prod.example.com;

    # SSL 证书
    ssl_certificate /etc/nginx/ssl/prod.example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/prod.example.com.key;

    # SSL 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # 安全头
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # 前端静态文件
    root /opt/soft/app-client;
    index index.html;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;

    # 代理新系统后端 API
    location /api/ {
        proxy_pass https://prod-backend.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;
        proxy_set_header Cookie $http_cookie;
        proxy_http_version 1.1;

        # 超时设置
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # 代理旧系统
    location /old-system/ {
        proxy_pass https://old-system-prod.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;
        proxy_set_header Cookie $http_cookie;
        proxy_http_version 1.1;

        # Cookie 处理
        proxy_cookie_domain old-system-prod.example.com $host;
        proxy_cookie_flags ~ secure httponly samesite=none;
    }

    # Vue Router history 模式
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源缓存(更长的过期时间)
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # 日志
    access_log /var/log/nginx/prod.access.log;
    error_log /var/log/nginx/prod.error.log;
}

第六章:问题排查与调试

6.1 网络连通性测试

测试工具对比
工具 协议 用途 示例
ping ICMP 测试网络可达性 ping 192.168.1.100
curl HTTP 测试 HTTP 服务 curl -I http://192.168.1.100:8080
telnet TCP 测试端口连通性 telnet 192.168.1.100 8080
nc TCP/UDP 多功能网络工具 nc -zv 192.168.1.100 8080
ping vs HTTP 请求
复制代码
ping 测试
  └─ 使用 ICMP 协议
  └─ 不经过端口
  └─ 容易被防火墙阻止
  └─ ping 不通 ≠ HTTP 访问不通

HTTP 请求(curl/浏览器)
  └─ 使用 HTTP 协议(TCP)
  └─ 经过具体端口(如 8080)
  └─ 更接近实际应用场景
  └─ 能测试服务是否正常

示例

bash 复制代码
# 1. ping 测试(可能被防火墙阻止)
ping 192.168.1.100
# 结果:请求超时

# 2. curl 测试(HTTP 协议)
curl -I http://192.168.1.100:8080/app/page
# 结果:HTTP/1.1 200 OK
# 说明:服务正常,只是 ICMP 被阻止了

6.2 浏览器开发者工具

Network 面板关键信息
复制代码
Network 面板
├─ Request URL:请求的完整 URL
│   └─ 检查是否走了代理路径
│
├─ Status:响应状态码
│   ├─ 200:成功
│   ├─ 401/403:认证/授权失败(Cookie 问题)
│   ├─ 404:路径错误
│   ├─ 502/504:代理后端无响应
│   └─ (failed) CORS error:跨域错误
│
├─ Request Headers:请求头
│   ├─ Origin:请求来源
│   ├─ Referer:引用页面
│   └─ Cookie:是否携带 Cookie ⭐
│
└─ Response Headers:响应头
    ├─ Access-Control-Allow-Origin:CORS 配置
    ├─ Set-Cookie:服务器设置的 Cookie ⭐
    └─ Content-Type:响应类型

步骤

  1. F12 打开开发者工具
  2. 切换到 Network 标签
  3. 勾选 "Preserve log"
  4. 刷新页面或触发请求
  5. 找到目标请求,点击查看详情
  6. 查看 Request Headers → 找 Cookie: 字段

判断

复制代码
✅ 有 Cookie 字段
  Cookie: sessionId=xxx; userId=yyy
  → Cookie 成功携带

❌ 没有 Cookie 字段
  → Cookie 未携带,需要检查:
     1. 是否跨域?
     2. SameSite 属性是否正确?
     3. 代理配置是否正确?

步骤

  1. Network 标签中找到登录请求
  2. 查看 Response Headers
  3. Set-Cookie: 字段
  4. 检查属性

重点关注

复制代码
Set-Cookie: sessionId=xxx; Path=/; HttpOnly; SameSite=Lax
                                              ↑
                                        检查这个属性

SameSite=Strict → iframe 不会携带 ❌
SameSite=Lax    → iframe 不会携带 ❌
SameSite=None   → iframe 会携带 ✅(需配合 Secure)

Application 面板

  1. F12 → Application 标签
  2. 左侧展开 Cookies
  3. 点击域名查看所有 Cookie
  4. 检查:
    • Name:Cookie 名称
    • Value:Cookie 值
    • Domain:作用域
    • Path:路径
    • Expires:过期时间
    • HttpOnly:是否仅HTTP
    • Secure:是否仅HTTPS
    • SameSite:同站策略

6.3 Nginx 日志分析

访问日志
bash 复制代码
# 实时查看访问日志
tail -f /var/log/nginx/access.log

# 或者项目特定的日志
tail -f /opt/soft/nginx/logs/access.log

日志格式

复制代码
203.0.113.20 - - [15/Jan/2026:17:41:12 +0800]
"GET /old-system/app/page HTTP/1.1" 200 15234
"http://203.0.113.10:8082/test/old-system-iframe"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/143.0.0.0"

分析要点

  • 客户端 IP
  • 请求时间
  • 请求方法和路径
  • 状态码(200/404/502等)
  • 响应大小
  • Referer(请求来源)
  • User-Agent(浏览器信息)
错误日志
bash 复制代码
# 实时查看错误日志
tail -f /var/log/nginx/error.log

常见错误

复制代码
# 后端连接超时
upstream timed out (110: Connection timed out)
while connecting to upstream
→ 后端服务器无响应或不可达

# 后端拒绝连接
connect() failed (111: Connection refused)
while connecting to upstream
→ 后端服务未启动或端口错误

# 找不到上游服务器
no resolver defined to resolve xxx
→ DNS 解析问题

# 权限问题
open() "/path/to/file" failed (13: Permission denied)
→ 文件权限不足

6.4 常见问题排查流程

问题1:请求跨域

现象

复制代码
Console 报错:
Access to XMLHttpRequest at 'http://...' from origin 'http://...'
has been blocked by CORS policy

排查步骤

复制代码
1. 检查 Request URL
   └─ 是否走了代理路径?
       ✅ /old-system/xxx → 正确
       ❌ http://192.168.x.x/xxx → 没走代理

2. 如果没走代理
   └─ 检查前端代码 iframe src
   └─ 检查 Vite/Nginx 配置
   └─ 重启服务

3. 如果走了代理还跨域
   └─ 检查后端 CORS 配置
   └─ 添加必要的响应头
问题2:Cookie 未携带

现象

复制代码
第一个请求(登录):成功
第二个请求(业务接口):401/403 未授权

排查步骤

复制代码
1. 检查 Network → Request Headers
   └─ 有 Cookie 字段吗?
       ❌ 没有 → 继续排查
       ✅ 有但值不对 → 后端问题

2. 检查 Set-Cookie 响应头
   └─ SameSite 属性是什么?
       Lax/Strict → 需要改为 None
       None → 检查是否有 Secure

3. 检查代理配置
   └─ proxy_set_header Cookie 配置了吗?
   └─ Cookie 重写配置正确吗?

4. 检查浏览器环境
   └─ 是否是 HTTPS?(SameSite=None 需要)
   └─ 浏览器是否阻止第三方 Cookie?
问题3:代理无法访问后端

现象

复制代码
Network 显示:(pending) 一直等待
或:502 Bad Gateway

排查步骤

复制代码
1. 确认代理服务器能访问后端
   └─ SSH 登录到代理服务器
   └─ 执行:curl -I http://后端地址

2. 检查网络可达性
   └─ 公网服务器访问内网地址?
       └─ ❌ 不可达
   └─ 解决:使用测试环境地址或内网穿透

3. 检查后端服务状态
   └─ 服务是否启动?
   └─ 端口是否正确?
   └─ 防火墙是否阻止?

4. 检查 Nginx 日志
   └─ tail -f /var/log/nginx/error.log
   └─ 查看具体错误信息

第七章:安全性考虑

7.1 CSRF 攻击与防护

CSRF 攻击原理
复制代码
用户正常访问网站A
  ↓
登录成功,浏览器保存 Cookie
  ↓
用户在同一浏览器访问恶意网站B
  ↓
恶意网站B 的代码:
<form action="https://网站A/api/deleteUser" method="POST">
  <input type="hidden" name="userId" value="123">
</form>
<script>document.forms[0].submit()</script>
  ↓
浏览器自动带上网站A的 Cookie 发送请求
  ↓
网站A 收到请求,验证 Cookie 通过
  ↓
❌ 执行了恶意操作(删除用户)
SameSite 的防护作用
复制代码
SameSite=Lax/Strict
  └─ 跨站请求不带 Cookie
  └─ 恶意网站的表单提交不会带 Cookie
  └─ ✅ 阻止 CSRF 攻击

SameSite=None
  └─ 跨站请求会带 Cookie
  └─ 恶意网站的请求也会带 Cookie
  └─ ❌ 无法防止 CSRF
使用 SameSite=None 的风险
复制代码
风险1:CSRF 攻击
  └─ 解决:添加 CSRF Token

风险2:信息泄露
  └─ 解决:敏感操作二次验证

风险3:会话劫持
  └─ 解决:使用 HTTPS + Secure
CSRF Token 防护方案

原理

复制代码
1. 用户登录后,服务器生成随机 Token
2. Token 存储在服务器 Session 或数据库
3. Token 返回给前端(非 Cookie 方式)
4. 前端每次请求都带上 Token(通常在请求头)
5. 服务器验证 Token 是否有效

实现示例

后端(Java/Spring):

java 复制代码
@RestController
public class AuthController {

    @PostMapping("/login")
    public LoginResponse login(@RequestBody LoginRequest request) {
        // 验证用户名密码
        User user = authService.authenticate(request.getUsername(), request.getPassword());

        // 生成 Session 和 CSRF Token
        String sessionId = UUID.randomUUID().toString();
        String csrfToken = UUID.randomUUID().toString();

        // 存储到 Redis
        redisTemplate.opsForValue().set("session:" + sessionId, user.getId());
        redisTemplate.opsForValue().set("csrf:" + sessionId, csrfToken);

        // 设置 Cookie(SameSite=None)
        Cookie cookie = new Cookie("sessionId", sessionId);
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setSecure(true);
        cookie.setAttribute("SameSite", "None");
        response.addCookie(cookie);

        // 返回 CSRF Token(通过响应体)
        return new LoginResponse(user, csrfToken);
    }

    @PostMapping("/api/protected")
    public Response protectedOperation(
        @CookieValue("sessionId") String sessionId,
        @RequestHeader("X-CSRF-Token") String csrfToken
    ) {
        // 验证 CSRF Token
        String expectedToken = redisTemplate.opsForValue().get("csrf:" + sessionId);
        if (!csrfToken.equals(expectedToken)) {
            throw new SecurityException("Invalid CSRF token");
        }

        // 执行操作
        return doProtectedOperation();
    }
}

前端(Vue):

typescript 复制代码
// 登录后保存 CSRF Token
const login = async (username: string, password: string) => {
  const response = await axios.post('/api/login', { username, password })
  // CSRF Token 存储在 localStorage(不是 Cookie)
  localStorage.setItem('csrfToken', response.data.csrfToken)
}

// 请求拦截器:自动添加 CSRF Token
axios.interceptors.request.use((config) => {
  const csrfToken = localStorage.getItem('csrfToken')
  if (csrfToken) {
    config.headers['X-CSRF-Token'] = csrfToken
  }
  return config
})

// 业务请求
const deleteUser = async (userId: string) => {
  // CSRF Token 会自动添加到请求头
  await axios.post('/api/deleteUser', { userId })
}

7.2 XSS 攻击防护

复制代码
iframe 嵌入场景的 XSS 风险
  ├─ 旧系统可能有 XSS 漏洞
  ├─ 通过 iframe 注入恶意脚本
  └─ 窃取新系统的数据

防护措施:
  ├─ Content-Security-Policy(CSP)
  ├─ X-Frame-Options
  └─ sandbox 属性

CSP 配置

nginx 复制代码
# Nginx 配置
add_header Content-Security-Policy "
  default-src 'self';
  script-src 'self' 'unsafe-inline';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  frame-src 'self' https://trusted-old-system.com;
";

iframe sandbox

html 复制代码
<!-- 限制 iframe 的能力 -->
<iframe src="/old-system/app/page" sandbox="allow-scripts allow-same-origin allow-forms"> </iframe>

<!-- sandbox 属性说明:
  allow-scripts: 允许执行脚本
  allow-same-origin: 允许同源访问
  allow-forms: 允许表单提交
  allow-top-navigation: 允许顶层导航(谨慎使用)
-->

7.3 HTTPS 最佳实践

为什么需要 HTTPS
复制代码
1. SameSite=None 必须配合 Secure(HTTPS)
2. 防止中间人攻击
3. 保护敏感数据传输
4. 提升 SEO 排名
5. 浏览器安全提示
SSL/TLS 配置
nginx 复制代码
server {
    listen 443 ssl http2;
    server_name prod.example.com;

    # SSL 证书(推荐使用 Let's Encrypt)
    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    # SSL 协议(禁用不安全的版本)
    ssl_protocols TLSv1.2 TLSv1.3;

    # 加密套件(优先使用安全的)
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;

    # Session 缓存
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # HSTS(强制 HTTPS)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # OCSP Stapling(提升 SSL 性能)
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
}

第八章:性能优化

8.1 Nginx 优化

nginx 复制代码
# 性能优化配置

# 工作进程数(通常设置为 CPU 核心数)
worker_processes auto;

# 每个进程的最大连接数
events {
    worker_connections 4096;
    use epoll; # Linux 下使用 epoll
}

http {
    # 开启 Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 1024;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/rss+xml
        font/truetype
        font/opentype
        application/vnd.ms-fontobject
        image/svg+xml;

    # 文件描述符缓存
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # 代理缓冲
    proxy_buffering on;
    proxy_buffer_size 8k;
    proxy_buffers 32 8k;
    proxy_busy_buffers_size 16k;

    # 代理超时
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;

    # 静态资源缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

8.2 前端优化

代码分割
typescript 复制代码
// 路由懒加载
const routes = [
  {
    path: '/test/old-system-iframe',
    component: () => import('@/views/test/OldSystemIframe.vue'),
  },
]
资源预加载
html 复制代码
<!-- index.html -->
<head>
  <!-- 预连接到旧系统 -->
  <link rel="preconnect" href="https://old-system.example.com" />
  <link rel="dns-prefetch" href="https://old-system.example.com" />
</head>
iframe 延迟加载
vue 复制代码
<script setup lang="ts">
import { ref, onMounted } from 'vue'

const showIframe = ref(false)

// 页面加载完成后再加载 iframe
onMounted(() => {
  setTimeout(() => {
    showIframe.value = true
  }, 500)
})
</script>

<template>
  <div class="iframe-wrapper">
    <iframe v-if="showIframe" src="/old-system/app/page" loading="lazy" />
    <div v-else class="loading">加载中...</div>
  </div>
</template>

第九章:监控与告警

9.1 Nginx 访问日志分析

日志格式定义
nginx 复制代码
http {
    log_format detailed '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_referer" "$http_user_agent" '
                       '$request_time $upstream_response_time '
                       '$upstream_addr $upstream_status';

    access_log /var/log/nginx/access.log detailed;
}
关键指标监控
bash 复制代码
# 实时监控代理请求
tail -f /var/log/nginx/access.log | grep '/old-system/'

# 统计状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 统计响应时间(找出慢请求)
awk '{if ($NF > 1) print $0}' /var/log/nginx/access.log

# 统计访问最多的 URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
性能监控
typescript 复制代码
// 监控 iframe 加载时间
const monitorIframeLoad = () => {
  const startTime = performance.now()

  const iframe = document.querySelector('iframe')
  if (iframe) {
    iframe.addEventListener('load', () => {
      const loadTime = performance.now() - startTime
      console.log('Iframe load time:', loadTime, 'ms')

      // 上报性能数据
      reportPerformance({
        type: 'iframe-load',
        duration: loadTime,
        url: iframe.src,
      })
    })
  }
}

第十章:总结与最佳实践

10.1 问题解决方案总结

问题 开发环境方案 测试/生产环境方案
跨域 Vite 代理 Nginx 代理
Cookie携带 Cookie重写 + 代理 后端设置SameSite=None + Nginx代理
网络隔离 访问本地内网地址 使用测试环境地址或VPN
安全性 相对宽松(开发调试) HTTPS + CSRF Token + CSP

10.2 技术选型建议

场景1:内部系统集成(推荐)
复制代码
方案:代理方案
  ├─ 开发:Vite 代理
  ├─ 测试/生产:Nginx 代理
  └─ 优点:
      ├─ 彻底解决跨域
      ├─ Cookie 自动携带
      ├─ 无需后端大量改动
      └─ 统一域名,便于管理
场景2:第三方系统集成
复制代码
方案:postMessage 通信
  ├─ iframe 嵌入第三方页面
  ├─ 通过 postMessage 传递数据
  └─ 优点:
      ├─ 安全隔离
      ├─ 不依赖 Cookie
      └─ 适合不可控的第三方系统
场景3:微前端架构
复制代码
方案:qiankun 等微前端框架
  ├─ 子应用独立运行
  ├─ 主应用统一加载
  └─ 优点:
      ├─ 技术栈无关
      ├─ 独立部署
      ├─ 样式隔离
      └─ 适合大型多系统集成

10.3 配置清单

开发环境
复制代码
✅ vite.config.ts 配置代理
✅ iframe 使用代理路径
✅ 重启 Vite 服务
✅ 清除浏览器缓存测试
测试环境
复制代码
✅ Nginx 配置代理
✅ 确保测试服务器能访问后端
✅ 前端代码使用代理路径
✅ 重新打包部署
✅ 重载 Nginx 配置
✅ 清除浏览器缓存测试
生产环境
复制代码
✅ 配置 HTTPS 和 SSL 证书
✅ Nginx 代理配置(使用生产地址)
✅ 后端设置 SameSite=None; Secure
✅ 添加 CSRF Token 验证
✅ 配置 CSP 安全头
✅ 性能优化(Gzip、缓存等)
✅ 配置监控和告警
✅ 完整测试验证

10.4 注意事项

安全性
复制代码
⚠️ SameSite=None 会降低 CSRF 防护
  └─ 解决:添加 CSRF Token 验证

⚠️ iframe 可能存在 XSS 风险
  └─ 解决:使用 CSP 和 sandbox 属性

⚠️ 敏感信息不要存储在 Cookie
  └─ 解决:使用 HttpOnly 和加密

⚠️ 生产环境必须使用 HTTPS
  └─ 解决:申请 SSL 证书(Let's Encrypt 免费)
性能
复制代码
⚠️ iframe 会增加页面加载时间
  └─ 解决:延迟加载、预加载

⚠️ 代理会增加一层网络开销
  └─ 解决:Nginx 配置优化、启用缓存

⚠️ Cookie 过大会影响性能
  └─ 解决:精简 Cookie、使用 Session
兼容性
复制代码
⚠️ SameSite=None 需要较新的浏览器
  └─ 兼容:Chrome 80+, Firefox 69+, Safari 13+

⚠️ 部分浏览器完全阻止第三方 Cookie
  └─ Safari 默认阻止,需要用户手动开启

⚠️ 某些企业浏览器策略可能更严格
  └─ 解决:提供用户配置说明

10.5 故障处理预案

场景1:代理后端无响应
复制代码
现象:502 Bad Gateway / 504 Gateway Timeout

排查:
  1. 检查后端服务是否启动
  2. 检查网络连通性(curl 测试)
  3. 查看 Nginx error.log
  4. 检查防火墙和安全组配置

临时方案:
  1. 降级:显示友好提示,隐藏 iframe
  2. 切换:使用备用地址
场景2:Cookie 突然失效
复制代码
现象:用户频繁掉线、需要重新登录

排查:
  1. 检查 Set-Cookie 响应头是否变化
  2. 检查浏览器是否更新(策略变化)
  3. 检查服务器时间(Cookie 过期)
  4. 检查 Session 存储(Redis等)

解决:
  1. 调整 Cookie 过期时间
  2. 实现 Token 刷新机制
  3. 添加"记住我"功能
场景3:特定用户无法访问
复制代码
现象:部分用户报错,大部分用户正常

排查:
  1. 浏览器版本和设置
  2. 网络环境(VPN、代理)
  3. 企业安全策略
  4. 设备类型(移动端/PC)

解决:
  1. 提供浏览器兼容性说明
  2. 提供配置指南
  3. 提供降级方案

附录

A. 术语表

术语 英文 说明
跨域 Cross-Origin 浏览器安全策略,限制不同源之间的资源访问
同源策略 Same-Origin Policy 协议、域名、端口完全相同才算同源
CORS Cross-Origin Resource Sharing 跨域资源共享,允许服务器声明允许的跨域访问
CSRF Cross-Site Request Forgery 跨站请求伪造攻击
XSS Cross-Site Scripting 跨站脚本攻击
NAT Network Address Translation 网络地址转换
PNA Private Network Access 私有网络访问策略
CSP Content Security Policy 内容安全策略
HSTS HTTP Strict Transport Security HTTP 严格传输安全

B. 参考资源

浏览器安全

  • MDN Web Docs - Same-origin policy
  • MDN Web Docs - Cross-Origin Resource Sharing (CORS)
  • Chrome Platform Status - SameSite Cookies

网络基础

  • RFC 1918 - Address Allocation for Private Internets
  • RFC 6749 - The OAuth 2.0 Authorization Framework

Nginx 文档

Vite 文档

C. 快速参考卡片

Vite 代理配置模板
typescript 复制代码
export default defineConfig({
  server: {
    proxy: {
      '/prefix': {
        target: 'http://target-server:port',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/prefix/, ''),
      },
    },
  },
})
Nginx 代理配置模板
nginx 复制代码
location /prefix/ {
    proxy_pass http://target-server:port/;
    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 Cookie $http_cookie;
    proxy_http_version 1.1;
}
复制代码
Set-Cookie: name=value;
  Path=/;
  Domain=.example.com;
  HttpOnly;
  Secure;
  SameSite=None;
  Max-Age=86400

文档结束

本文档基于真实项目经验总结,涵盖了 iframe 跨域问题的完整解决方案,从问题分析、技术原理、实施方案到安全性和性能优化,提供了全面的实践指导。希望对遇到类似问题的开发者有所帮助。

相关推荐
小雨青年2 小时前
鸿蒙 HarmonyOS 6 | 逻辑核心 (04):原生网络库 RCP 高性能实战
网络·华为·harmonyos
企业对冲系统官2 小时前
价格风险管理平台审批角色配置与权限矩阵设计
大数据·运维·开发语言·前端·网络·数据库·矩阵
以太浮标2 小时前
华为eNSP模拟器综合实验之- 端口安全MAC地址表
网络
乾元2 小时前
专栏案例合集:AI 网络工程交付的完整闭环—— 从 Demo 到 Production 的工程化方法论
运维·开发语言·网络·人工智能·架构·自动化
我的炸串拌饼店2 小时前
C# 邮件发送与附件处理详解
开发语言·网络·c#
向上的车轮2 小时前
TCP/IP 协议解析:ChatDemo
网络·网络协议·tcp/ip
8K超高清2 小时前
超高清智能数字影像技术重构产业逻辑,国产摄像机品牌异军突起
网络·人工智能·科技·数码相机·计算机视觉·重构
brave and determined2 小时前
工程设计类学习(DAY6):PCB可制造性设计规范全解析
网络·嵌入式硬件·学习·pcb设计·设计规范·嵌入式设计·设计工艺
人工智能知识库2 小时前
H3CNE-Security安全GB0-510题库(带详细解析)
网络·安全·题库·h3cne·h3cne-security·gb0-510