一、跨域问题概述
has been blocked by CORS policy:No 'Access-Control-Allow-Origin'
相信这个跨域的问题大家并不陌生。
二、常规解决方案
来看一下常规的解决方案:
常规的解决跨域问题方案主要包括以下几种:
- JSONP:通过动态创建<script>标签,将数据以JSONP形式返回到前端页面。由于<script>标签不受同源策略的限制,因此可以实现跨域访问。
- CORS(跨域资源共享):在服务端设置响应头部中的Access-Control-Allow-Origin字段,授权指定的域名进行跨域访问。CORS需要浏览器和服务器双方都支持,且只适用于XMLHttpRequest请求。
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addExposedHeader("*");
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
- 反向代理:将前端请求先发送到同源的后端服务器,然后由后端服务器转发请求到目标服务器,最后再将结果返回给前端页面。这种方式需要部署额外的服务器进行代理,但能够解决通用性较好的跨域问题。
小结:
可以发现前2种方法,大多部分场景下都已经没效果了,当然第3种还是可以的。
三、一些特殊情况
1、调用localhost服务问题
不过还有很多场景没法使用反向代理。比如页面要调用c++的本地服务,在本地就没法代理了。这种场景在以前好像也是可以正常调用的,不过chrome浏览器在2021升级过一次,也就是在 chrome v94 之后 ,chrome浏览器会有这么个提示:
Access to Css stylesheet at ‘http:xx’ from origin ‘ http://xx‘ has been blocked by CORS policy: The request client is not a secure context and the resource is in more-prevate adddress space local
可以看到“local”也就是调用http://localhost (或 http://127.0.0.0)浏览器出于安全考虑会阻止此请求。当然问题出来了也就会有相应的解决方案。
- 方案一、访问本地数据
访问 http://localhost (或 http://127.*.*.*, http://[::1]) 则只需要把浏览的页面升级为 https 即可
- 方案二、chrome设置
在试验阶段, 可以设置 chrome 浏览器 chrome://flags/#block-insecure-private-network-requests 值为 disabled, 但这预计会在 chrome v101 失效
当然后续的版本也有这个配置
在新版本我尝试了下,好像都不管用了。
- 方案三、websocket
其实从图一中可以看出websocket也是存在跨域问题的,但websocket协议没有同源策略的限制。
图二中说明websocket建立连接前会先使用http请求通过后再升级协议成websocket也就是说这里的http会不会也被跨域而阻断了请求,再看第三张图,http get是不受跨域影响的,正好websocket建立连接用的就是http get。
小结:websocket可以解决跨域造成的客户端与服务器无法通信的问题。
四、总结
总结:解决跨域的终级方案
- 方案一:升级成https通信
- 方案二:使用websocket通信
五、技术笔记
- http get没有跨域问题
- http post有跨域问题,同时限制双方通信
- websocket有跨域问题,但并不限制双方通信