跨域问题总结
简单总结:
跨域的发生是 前端页面 发起了 异源的非简单请求 的行为,会触发的客户端和服务端的确认机制,由客户端(一般是浏览器)向服务端发起一个请求方式为**OPTIONS**
的预见请求询问服务器是否允许实际的跨域请求
要理解跨域的行为机制和跨域问题的解决办法,需要理清楚以下几个概念:
同源和异源的概念
同源请求(Same-Origin Request)是指浏览器从当前文档的源发起的请求,且请求的目标地址与当前文档的源相同。在 Web 开发中,源(Origin)由三个部分组成:
- 协议(Protocol)
- 域名(Domain)
- 和端口号(Port)
只有当这三个部分都相同时,请求才会被认为是同源的。否则就是异源请求;
简单请求和非简单请求
非简单请求(Non-Simple Request)是跨源资源共享(CORS)中的概念,它指的是不符合简单请求(Simple Request)条件的请求。根据 CORS 规范,一个请求要被认为是“简单”的,必须满足以下所有条件:
使用简单方法:
请求必须使用以下方法之一:
- GET
- POST
- HEAD
使用简单头部:
请求中的 HTTP 请求头必须至少包括以下字段之一,且不能包含其他字段:
- Accept
- Accept-Language
- Content-Language
- Content-Type(只限于以下三个值之一)
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
没有额外的请求头:
请求不能包含任何其他自定义请求头。
没有请求体:
对于 POST 请求,如果 Content-Type 是application/x-www-form-urlencoded、multipart/form-data
或 text/plain
之一,则请求体是允许的。除此之外,如果 POST 请求包含请求体,那么它将被视为非简单请求。
不使用 HTTP 扩展:
请求不能使用任何 HTTP 扩展,例如,不能在请求中包含 PUT、DELETE、CONNECT
等方法。
如果一个请求不满足上述所有条件,它就会被视为非简单请求。
报错样式
network 报错
console 报错
服务端如何处理跨域
跨域校验机制
非简单请求在发送之前,浏览器会先发送一个预检请求(preflight request)到服务器,询问服务器是否允许实际的跨域请求。
预检请求是一个 OPTIONS
请求,它包含了 Access-Control-Request-Method
和 Access-Control-Request-Headers
头部,分别表示实际请求将使用的方法和头部信息。
服务端处理方式
服务器必须在响应中正确设置 CORS 相关的头部,如 :
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
才能允许跨域请求。
如果服务器响应允许,浏览器才会发送实际的请求,否则不会发起后续的请求;
*不能在 Access-Control-Allow-Origin 中使用通配符 (除非服务器确实打算接受来自任何源的请求)
前端如何处理跨域
前端其实没有办法解决跨域问题,这是浏览器的一个强限制,一般的解决方案都是来规避【浏览器的同源策略】
代理服务器
在前端应用和后端 API 之间设置一个代理服务器,这样前端的请求首先发送到代理服务器,然后由代理服务器转发到目标 API。这种方式可以绕过浏览器的同源策略。
JSONP(仅限于 GET 请求):
通过动态创建<script>
标签的方式,可以绕过同源策略的限制。但这种方法只支持 GET
请求,且存在安全风险,现在已经较少使用。
浏览器插件:
在开发阶段,可以使用浏览器插件来临时绕过同源策略的限制,但这不适用于生产环境。