原因:跨域是由于浏览器存在同源策略,两个页面之间,如果协议、主机和端口中有任意一个不同,就会出现跨域问题
现象:
- Cookie、LocalStorage、IndexDB 无法读取;
- DOM 和 JS 对象无法获取;
- AJAX 请求无法发送
解决方案:
- JSONP 跨域
一些标签如<script>
、<img>
没有跨域限制,利用src属性发送带有callback参数的GET请求,服务器将数据传入到callback函数中,返回给浏览器解析运行,从而在前端拿到数据。
缺点:只能发起 GET 请求
// 前端代码
<script>
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://localhost:3000/login?name=lisa&callback=handle';
document.head.appendChild(script);
function handle(res){
alert(res); // 弹出name的值, 即lisa
}
</script>
// node服务端代码
const Koa = require('koa');
const router = require('koa-router')(); //注意:引入的方式
const app = new Koa();
router.get('/login', function (ctx, next) {
let request = ctx.request
let query = request.query
let name = query.name
let fn = query.callback
ctx.body = fn + '(' + JSON.stringify(name) + ')'
})
app.use(router.routes()); //作用:启动路由
app.use(router.allowedMethods());
app.listen(3000,()=>{
console.log('starting at port 3000');
});
- CORS(跨域资源共享)
它允许浏览器向跨域服务器发起 XMLHttpRequest 请求,从而避开 Ajax 的同源限制。
CORS 请求需要浏览器和服务器都支持,所有浏览器都支持,IE 浏览器不能低于 IE10,可分为2种类型:简单请求和复杂请求
- 简单请求: 满足以下2个条件即为简单请求
(1) 请求方法是以下三种方法之一:HEAD、GET、POST
(2)HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段,指明了本次请求的来源(协议+主机+端口)。服务器根据这个值来判断是否同意这次请求。
可在服务器对下面3个属性进行设置来实现 CORS 跨域
(1)Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
(2)Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
(3)Access-Control-Expose-Headers
该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。
- 非简单请求
- nginx 反向代理
#proxy服务器
server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass http://www.domain2.com:8080; #反向代理
proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
index index.html index.htm;
# 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
add_header Access-Control-Allow-Origin http://www.domain1.com; #当前端只跨域不带cookie时,可为*
add_header Access-Control-Allow-Credentials true;
}
}
- vue.config.js 配置 proxy 代理
devServer: {
// 首次打包成功后,自动打开浏览器
open: true,
// 在 http 协议中,如果端口号是 80,则可以被省略
port: 8099,
// 指定运行的主机地址
host: '127.0.0.1',
proxy: {
'/api': {
target: 'http://localhost:10003', // 目标的服务器接口
changOrigin: true, // 允许跨域
pathRewrite: {
/* 重写路径,当我们在浏览器中看到请求的地址为:http://localhost:8080/api/core/getData/userInfo 时
实际上访问的地址是:http://localhost:8080/core/getData/userInfo,因为重写了 /api
*/
'^/api': ''
}
}
}
}