身为一个码农,在日常的开发过程中难免遇到API接口跨域的问题,今天主要整理一下导致跨域问题的原因以及常用的解决方案。
导致跨域问题的原因?
跨域问题其实是由浏览器的同源策略导致的。
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
常用的解决方案
解决跨域问题的方式有很多,一般有下面几种:
1、 Cross-Origin Resource Sharing(CORS)跨域资源
2、JSONP
3、反向代理
4、document.domain
5、使用postMessage
6、WebSocket
7、关闭浏览器跨域限制(disable-web-security)
然而,在实际的开发过程中我们一般最常用的解决方案是CORS和反向代理。
跨域资源共享(CORS)
跨域资源共享(Cross-Origin Resource Sharing,简称 CORS),是 HTML5 提供的标准跨域解决方案。相较于JSONP的方式,CORS具有更多优势:
JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
不过使用CORS来解决跨域问题需要服务端支持,然后通过设置Access-Control-Allow-Origin来解决跨域问题。
服务端如何实现CORS跨域资源共享?
我们以node
服务为例,因为我个人比较喜欢使用koa2来进行Restful API的开发, 所以我们可以通过koa2-cors
来快速实现服务对CORS
的支持,具体实现示例代码:
var koa = require('koa');
var app = new koa();
var router = require('koa-router')();
//引入koa2-cors库
const cors = require('koa2-cors');
app.use(cors({
origin: function (ctx) {
return "*"; // 允许来自所有域名请求
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}))
router.post('/', async function (ctx) {
ctx.body = 'hello,world'
});
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(3000);
反向代理
除了使用CORS
之外,我们也会经常通过设置反向代理服务来解决跨域问题。
一般情况下,我们可以直接通过配置nginx
服务器来实现反向代理功能;
因为我们公司后端是采用了微服务架构+网关(kong),所以可以直接在kong
里面配置路由规则;
如果自己是前端开发者并且使用了vue
进行前端项目开发,我们只可以打开项目中config文件夹下index.js文件,然后在dev.proxyTable
添加配置信息就可以了。示例:
var path = require('path')
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: 8087,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
//################################################################配置信息
proxyTable: {
'/api': {
target: 'http://13.63.***.**',//填写需要代理的真实地址
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
},
//################################################################配置信息
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}
补充
如果我们希望可以最快速的解决跨域问题,然后进行临时调试,我们可以直接通过关闭chrome的安全设置(不推荐)。
具体实现方式
1、在桌面找到浏览器快捷图标并点击鼠标右键的属性一栏
2、在属性页面中的目标输入框里加上 --disable-web-security --user-data-dir=C:\MyChromeDevUserData
,user-data-dir
可以是任意路径,如下图所示:
3、保存并重启浏览器