心脏骤停的开始

更适合全栈宝宝体质

作为一名有着丰富bug经验的pre全栈开发工程师,你熟练的建立起了当下十分流行的前后端分离项目:

  • 使用vite脚手架建立了前端模板
  • 使用node建立了简单的接口

进行了简单的开发后你开始了测试

Untitled

Untitled

页面OK 接口OK,接下来就是在页面中调用接口

1
2
// demo to call localhost:8080
fetch('http://localhost:8080').then(res => res.text()).then(console.log)

诶,这是什么?

Untitled

更适合前端(静态)宝宝体质

作为一名有着丰富blog经验的前端er,某天你心血来潮打算给自己的博客加一些炫酷的字体。你自信的完成了配置工作,却发现由于服务器带宽限制,字体文件过大加载很慢

于是你机智的把静态资源部署到了大带宽的服务上(OSS)可是设置后。。

我字体怎么不显示??

诶,这是什么?

Untitled


CORS

Untitled

从搜索列表中不难看出,大家对CORS的热情不输与css如何居中(doge)

那么问题来了

什么是CORS

跨源资源共享CORS,或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他(域、协议或端口),使得浏览器允许这些源访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。

浏览器? 服务器? 自己?

我超!源

要知道什么是跨源就要知道什么是同源。

从上面的定义可以知道,我们将域、协议或端口的组合成为源,也就是说,域、协议或端口任意一个不一样都是不同的源。

Untitled

也就是说,浏览器只允许服务器加载一个自己(托管)的资源了?那我怎么前后端分离?为什么要CORS?

为什么要CORS

作为已修北京邮电大学国际学院物联网工程大三上学期必修课中间件技术的各位应该在期末复习时见过 CSRF(跨站请求伪造) 这个概念

巧不巧,这里也有跨站这个词,我们让chatgpt举个例

当网站没有正确实施 CORS 策略时,可能会导致 CSRF(跨站请求伪造)攻击。以下是一个简单的示例:

假设有两个网站:https://www.example.comhttps://www.evil.com

  1. 用户在 https://www.example.com 登录并获得了一个持久的会话(session)。
  2. https://www.example.com 中,存在一个通过 GET 请求更改用户密码的端点,如 https://www.example.com/change-password
  3. https://www.evil.com 中,存在一个恶意页面,其中包含以下 HTML 代码:
1
2
3
4
5
6
<form id="csrf-form" action="https://www.example.com/change-password" method="POST">
<input type="hidden" name="new-password" value="evilpassword">
</form>
<script>
document.getElementById('csrf-form').submit();
</script>
  1. 当用户在已登录的状态下访问 https://www.evil.com,恶意页面会自动向 https://www.example.com/change-password 发送 POST 请求,因为用户在 https://www.example.com 中已经登录,浏览器会自动发送相应的认证信息(如 Cookie)。
  2. 由于 https://www.example.com 没有实施 CORS 策略,因此浏览器会发送 POST 请求给 https://www.example.com,并成功更改了用户的密码,而用户可能完全不知情。

在这个示例中,由于缺乏 CORS 策略,恶意网站 https://www.evil.com 可以利用用户在其他网站中的身份验证信息,伪装用户发送恶意请求,从而实现 CSRF 攻击。通过实施正确的 CORS 策略,服务器可以限制跨域请求的来源,从而防止此类攻击。

所以说,浏览器确实应该拦截所有的非同源请求。


重看心脏骤停的开始

Untitled

首先,当我们打开5173端口时,浏览器向前端服务器发送请求并接收响应。

此时浏览器保存了源=localhost:5173,在接下来的同源请求时正常显示

这时浏览器请求了8080端口并收到了来自localhost:8080的请求,这显然违背了同源原则所以导致了上面的错误


怎么办 怎么办 怎么办

前后端还要分离,跨域请求还要发,怎么办?

从原理上讲

我没需要配置非同源响应的http头,也就是(一般是)后端的配置。

挖个坑

从实践上讲

Nodejs

添加cors中间件

1
2
3
const cors = require('cors')
const server = express()
server.use(cors())

完整demoserver:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const cors = require('cors')
const express = require('express')

// 设置服务器端口
const PORT = 8080

// 创建服务器
const server = express()

// 设置服务器端口
server.listen(PORT)
// 设置跨域
server.use(cors(
{
origin: 'http://localhost:5173'
}
))
console.log('node-server started at port http://localhost:' + PORT)

// 设置路由
server.get('/', (req, res) => {
res.send('You got res from 8080!')
})

Springboot

使用配置类

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class CrossOriginConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("localhost:5173")
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true)
.maxAge(3600);
}
}

OSS-阿里云

Untitled

最后,再次访问

Untitled

跨域问题解决