解决跨域问题:No ‘Access-Control-Allow-Origin‘ header is present on the requested resource.

目录

错误信息

原因分析

简单请求

非简单请求

预检请求

请求回应


错误信息

我们先来看一下浏览器控制台的错误信息:

Ensure CORS response header values are valid
A cross-origin resource sharing (CORS) request was blocked because of invalid or missing response headers of the request or the associated preflight request .
To fix this issue, ensure the response to the CORS request and/or the associated preflight request are not missing headers and use valid header values.
Note that if an opaque response is sufficient, the request's mode can be set to no-cors to fetch the resource with CORS disabled; that way CORS headers are not required but the response content is inaccessible (opaque).

错误信息翻译:

确保CORS响应标头值有效
跨源资源共享(CORS)请求被阻止,原因是该请求或相关联的飞行前请求的响应标头无效或丢失。
要解决此问题,请确保对CORS请求和/或相关飞行前请求的响应没有丢失标头,并使用有效的标头值。
请注意,如果不透明的响应就足够了,则可以将请求的模式设置为无cors,以在禁用cors的情况下获取资源;这样就不需要CORS头,但是响应内容是不可访问的(不透明的)。 

原因分析

错误信息里提到了一句“确保CORS响应标头值有效”,那么什么是CORS呢?

CORS,全称Cross-Origin Resource Sharing,是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制,通常由于同域安全策略(the same-origin security policy)浏览器会禁止这种跨域请求

也就是说我们缺少了CORS响应标头值,或者是CORS响应标头值无效。那么就要从这个响应标头开始找问题,我们先来解释为什么要有CORS响应标头值。从错误信息“这样就不需要CORS头,但是响应内容是不可访问的(不透明的)”中可以看出,这个响应标头是必须的,否则即使成功响应了结果,也无法访问。

简单请求

浏览器直接发出CORS请求,会在请求标头中增加一个Origin字段,用来说明本次请求来自哪个源(请求协议 + 主机名 + 端口号),服务器会根据这个值来判断是否接受该请求。如果浏览器在响应头中没有发现Access-Control-Allow-Origin字段,说明请求不在许可范围内,在浏览器控制台中出现错误“No 'Access-Control-Allow-Origin' header is present on the requested resource.”。这个错误无法从状态码中识别,因为返回的状态码会是200 OK。

其实服务器是会返回请求结果的,但是浏览器拒绝接受结果。

那么我们知道了Access-Control-Allow-Origin字段是很重要的,这个字段的值为请求时Origin字段的值,请求的结果才能成功被浏览器接受。

Access-Control-Allow-Origin字段的值可以设为*,表示接受任意源的请求。

非简单请求

非简单请求是指对服务器有特殊要求的请求,例如POST请求和PUT请求,或者Content-Type字段的类型是application/json的请求。

预检请求

对于非简单的CORS请求,会在正式请求之前发起一次预检请求。

也就是说浏览器会先确认服务器是否接受该源的请求,只有在经过服务器同意之后,浏览器才会发出正式请求。

预检请求的请求方式是OPTIONS,请求标头中包含Origin字段,表示来自哪个源。此外预检请求还必须有Access-Control-Request-Method字段,用来说明浏览器接下来可能会发出的请求类型;Access-Control-Allow-Headers字段,用来指定浏览器CORS请求会额外发送的请求标头字段。

请求回应

对此服务器必须给浏览器响应预检请求想要的结果才行,否则浏览器不会向服务器发出正式请求。

后端可以在过滤器中或者是拦截器中设置响应标头,如下:

response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE,PATCH");
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));

在预检请求通过后,浏览器发出的正式请求就和简单请求一样。浏览器会在请求标头中增加一个Origin字段,服务器会在响应标头中增加Access-Control-Allow-Origin字段。

猜你喜欢

转载自blog.csdn.net/qq_74312711/article/details/134908533