浏览器中跨域的理解以及解决办法

180 阅读3分钟

要解决浏览器跨域问题 就要先了解什么是浏览器的同源策略

  • 同源策略是一个重要的安全策略,它用于限制一个origin(源)的文档或者它加载的脚本如何能与另一个origin(源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

当我们从静态资源服务器 请求到了html/css/js 在js中会包含着网络请求 这个时候就会经过浏览器的同源策略 如果 协议 host 端口不一致 就会出发CORS 产生跨域

浏览器发现静态资源和API接口(XHR、Fetch) 请求不是来自同一个地方时(同源策略),就产生了跨域。

同源策略是在保护服务器 防止未知脚本注册到服务器上 然后获取到数据触发利益的损害

  • 这个方案也被称为“协议/主机/端口元组”,或者直接是“元组”。

跨域的常用四种解决办法

  • 方案一:静态资源和API服务器部署在同一个服务器中;
  • 方案二:CORS, 即是指跨域资源共享;
  • 方案三:node代理服务器(webpack中就是它);
  • 方案四:Nginx反向代理;

1. 静态资源和api部署在一起

使用koa中的static(静态资源中间件) 部署到一起

1234.jpg 直接访问8080端口 也就是koa开启的服务器。 这样就把静态资源和api在同一个服务器中

这种方式会把单一的服务器内部资源占满 越来越多

2.CORS, 即是指跨域资源共享;

它是一种基于http header的机制; 该机制通过允许服务器标示除了它自己以外的其它源(域、协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。也就是说给服务器标识除了自己以外 还有谁可以来进行访问

浏览器将 CORS 请求分成两类:简单请求和非简单请求 Vue3+TypeScript

◼请求方法是以下是三种方法之一: HEAD GET POST

◼ HTTP 的头信息不超出以下几种字段:

Accept

Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain

满足上面的情况的都是简单请求 否则都是非简单请求

app.use(async (ctx, next) => {
  // 1.允许简单请求开启CORS *代表着所有源。 也可以单独设置一个
  ctx.set("Access-Control-Allow-Origin", "*")
  // 2.非简单请求开启下面的设置
  ctx.set("Access-Control-Allow-Headers", "Accept, AcceptEncoding, Connection, Host, Origin")
  ctx.set("Access-Control-Allow-Credentials", true) // cookie
  ctx.set("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, PATCH, OPTIONS")
  // 3.发起的是一个options请求
  if (ctx.method === 'OPTIONS') {
    ctx.status = 204
  } else {
    await next()
  }
})

3.node代理服务器(webpack中就是它);

如果直接访问api服务器就会出发浏览器的同源策略 所以可以开启一个node服务器(本质也就是node程序) 然后通过node服务器 来访问api服务器 因为是通过node服务器来访问 他不属于浏览器访问 所以不存在有跨域问题 其实webpack 配置中proxy也是使用的http-proxy-middleware软件包开启了一个node代理服务器

// webpack => webpack-dev-server
const express = require('express')
const { createProxyMiddleware } = require('http-proxy-middleware')

const app = express()

// 把代理服务器 和静态资源服务器部署到一起
app.use(express.static('./client'))

app.use('/api', createProxyMiddleware({
  target: "http://localhost:8000",
  pathRewrite: {
    '^/api': ''
  }
}))

app.listen(9000, () => {
  console.log('express proxy服务器开启成功')
})

4.使用Nginx 开启反向代理

WeChateee11caf6fd3f36be384b421376bde3f.png

Nginx 他可以在内部来进行源的验证 来阻拦其它未知源的访问。 避免暴漏api服务器的ip地址 提高安全性