cors
不知道大家有没有遇到过cors问题, 在刚开始写前后端时我还挺经常遇到这个问题的, 我还以为是我前端的问题, 一直改不好, 问ai也没给出答案(当时ai还挺拉的, 没有现在这么强), 浅浅在这里写一下.
同源策略
在写cors前有必要了解一下浏览器的同源策略.
为了安全性, 浏览器一般只允许同源的请求, 除了嵌入在页面的静态资源. 也就是说在js代码中域名A的网站是不能向域名B发送请求的.
跨域资源共享(CORS)
在早期前后端一体的时候这种做法基本没有问题, 但随着前后端发展, 前端和后端逐渐分离就出现问题了. 因此浏览器实现了一种机制来让网站自己决定谁能访问自己的资源. 这个机制叫*跨域资源共享(CORS)*机制.
js发送一个请求时, 浏览器会自动在请求头上加上一个Origin字段, 这个是自动的, 无法手动操控. 服务端也应该在响应头加上一个access-control-allow-origin
字段来告诉浏览器哪些源被允许. 如果服务器没有明确表明接受这个源, 那么浏览器就不会允许js代码读取响应.
也就是说如果access-control-allow-origin
里没有Origin
对应的地址, 浏览器不会允许这个请求.
但实际上, 这个请求后端还是接收并处理了(除非后端检测Origin并拒绝服务无关的Origin, 但是这不太可能). 如果是一些不需要读取响应只需要执行的敏感行为, 那攻击者还是得逞了. 因此, 浏览器又将请求分为两种请求: 简单请求和复杂请求.
简单请求
简单请求的判断
浏览器对简单请求的要求大概是这样的:
没有自定义响应头
方法必须是这三种之一:
- GET
- HEAD
- POST
Content-Type字段只允许这些内容:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
只有同时满足这些条件, 才是简单请求, 其它的都是复杂请求.
简单请求的处理
对于简单请求, 浏览器认为这是安全或者几乎没有风险的操作, 因此会直接发给服务端, 只是如果不被允许那就不让js读取响应, 但实际上服务器还是会处理响应.
复杂请求
复杂请求的判断
不是简单请求就是复杂请求
复杂请求的处理
对于复杂请求, 浏览器会先发送一个预检请求(OPTIONS), 来获取服务端的access-control-allow-origin
. 如果Origin
不在access-control-allow-origin
里, 那就不发送请求了, 并抛出错误.
如果Origin在access-control-allow-origin里, 那就正常发送请求.
解决跨域错误
如果是在开发环境, 可以选择本地搭建一个代理服务器, vite之类的东西有相关功能.
如果是生产环境, 可以使用nginx反向代理, 或者在后端代码中允许对应的域.