调用第三方WebService跨域报错:No 'Access-Control-Allow-Origin'
先看看你遇到的具体错误提示:
XMLHttpRequest cannot load http://xxxxxxxxx:yyyyy/sccwebclient/svc/filetransfers/?startedDay%3E2018-05-02T00%3A00%3A00。对预检请求的响应未通过访问控制检查:请求的资源上不存在'Access-Control-Allow-Origin'标头,因此源'http://localhost:8080'被拒绝访问。
这个问题我之前踩过坑,本质就是浏览器的同源策略限制——JavaScript在浏览器环境下发起跨域请求时,会自动触发预检(OPTIONS)请求,要求目标服务返回Access-Control-Allow-Origin这类CORS相关响应头,否则浏览器会直接拦截请求结果;而Postman、curl这类工具不受浏览器同源策略约束,所以能正常调用第三方服务。
下面给你几个可行的解决方案,你可以根据实际情况选:
如果你有权限修改第三方WebService的配置
直接在服务端添加CORS响应头即可:- 允许你的前端源访问:
Access-Control-Allow-Origin: http://localhost:8080(生产环境建议指定具体域名,别用*,尤其是带Cookie的请求) - 处理预检请求:返回
Access-Control-Allow-Methods(比如GET、POST这类允许的HTTP方法)和Access-Control-Allow-Headers(允许的请求头),确保OPTIONS请求能正常返回200状态码。
- 允许你的前端源访问:
如果无法修改第三方服务(这是最常见的情况)
给自己的前端服务加个代理转发:
比如你的前端跑在http://localhost:8080,可以在这个服务里新增一个接口(比如/api/proxy-filetransfers),前端调用这个同域接口,然后由你的后端去请求第三方的http://xxxxxxxxx:yyyyy/sccwebclient/svc/filetransfers/接口,再把结果返回给前端。这样就绕开了浏览器的跨域限制。
举个Node.js的例子,用http-proxy-middleware配置代理:const { createProxyMiddleware } = require('http-proxy-middleware'); app.use('/api/proxy-filetransfers', createProxyMiddleware({ target: 'http://xxxxxxxxx:yyyyy/sccwebclient/svc/', changeOrigin: true, pathRewrite: { '^/api/proxy-filetransfers': '/filetransfers' } }));之后前端直接调用
/api/proxy-filetransfers?startedDay>2018-05-02T00:00:00就可以了。本地临时调试用的快捷方法
可以装个浏览器跨域插件(比如Chrome的「Allow CORS: Access-Control-Allow-Origin」),开启后浏览器会自动给请求补上CORS头,临时解决调试问题,但绝对不能用于生产环境,这只是个调试工具而已。
内容的提问来源于stack exchange,提问作者user3061516

