CORS 跨域规则

建议点击 查看原文 查看最新内容。

原文链接: https://typonotes.com/posts/2024/03/19/cors-rules/

1. 因为 axios 封装遇到的跨域问题

本地服务器: http://127.0.0.1:5173, 后端服务器 http://127.0.0.1:8888。 服务器程序为 json-server

进行如下封装后, 出现跨域问题, 尝试搜索 json-server 允许跨域配置, 始终无果。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 封装 axios
const httpClient = axios.create({
    baseURL: 'http://localhost:8888',
    timeout: 5 * 1000,
    responseType: 'json',
})

// 请求拦截器规则 - 请求封装
const onRequest = (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {

    // 问题点在于这个 header
    config.headers.token = "token123456"

    return config;
}

// 使用请求拦截器
httpClient.interceptors.request.use(onRequest, onRequestError);


// 调用 httpClient 请求
const onButtonClickWithHttp = () => {
    httpClient.get('/ping').then(
        (res) => {
            // console.log(res.data.data)
            setNames(res.data.data)
        }
    )
}

之后将后端服务切换成 Golang 实现的一个简单 API Server, 并且配置跨域相关参数。 依旧不行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// go api server


	h.Use(cors.New(cors.Config{
		AllowOrigins: []string{
			"http://localhost:3000",
			"http://localhost:5173",
		},
		AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowWildcard: true,
	}))

2. 问题原因

后经搜索, 发现问题原因 请求体的 Header, 关于cors实现之简单请求与预检请求(发送请求头带令牌token) #5

关键点在于, 浏览器跨域访问控制场景

这里,我们使用三个场景来解释跨源资源共享机制的工作原理。这些例子都使用在任意所支持的浏览器上都可以发出跨域请求的 XMLHttpRequest 对象。

简单请求
某些请求不会触发 CORS 预检请求。在废弃的 CORS 规范中称这样的请求为简单请求,但是目前的 Fetch 规范(CORS 的现行定义规范)中不再使用这个词语。

其动机是,HTML 4.0 中的 <form> 元素(早于跨站 XMLHttpRequest 和 fetch)可以向任何来源提交简单请求,所以任何编写服务器的人一定已经在保护跨站请求伪造攻击(CSRF)。在这个假设下,服务器不必选择加入(通过响应预检请求)来接收任何看起来像表单提交的请求,因为 CSRF 的威胁并不比表单提交的威胁差。然而,服务器仍然必须提供 Access-Control-Allow-Origin 的选择,以便与脚本共享响应。

若请求满足所有下述条件,则该请求可视为简单请求:

使用下列方法之一:
  + GET
  + HEAD
  + POST
除了被用户代理自动设置的标头字段(例如 Connection、User-Agent 或其他在 Fetch 规范中定义为禁用标头名称的标头),允许人为设置的字段为 Fetch 规范定义的对 CORS 安全的标头字段集合。该集合为:
  + Accept
  + Accept-Language
  + Content-Language
  + Content-Type(需要注意额外的限制)
  + Range(只允许简单的范围标头值 如 bytes=256- 或 bytes=127-255)
  + Content-Type 标头所指定的媒体类型的值仅限于下列三者之一:
    + text/plain
    + multipart/form-data
    + application/x-www-form-urlencoded
如果请求是使用 XMLHttpRequest 对象发出的,在返回的 XMLHttpRequest.upload 对象属性上没有注册任何事件监听器;也就是说,给定一个 XMLHttpRequest 实例 xhr,没有调用 xhr.upload.addEventListener(),以监听该上传请求。
请求中没有使用 ReadableStream 对象。

3. 三个核心跨域 Header

  1. Access-Control-Allow-Origin 允许主机
  2. Access-Control-Allow-Method 允许方法
  3. Access-Control-Allow-Header 允许 Header