什么是跨域/跨源?
跨域是什么意思?跨源又是什么意思?好像只听说过跨域没听说过跨源,其实这两个是一回事
跨域问题指的是不同站点之间,使用 ajax 无法相互调用的问题。跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。 这个就是我们常说的同源策略(协议,域名,端口都相同就是同源)
同源策略是一种保护机制,那么非同源就是跨源了
但这个保护机制也带来了新的问题,它的问题是给不同站点之间的正常调用,也带来的阻碍
浏览器在向服务器发送请求的时候,协议,域名,端口三者任意一个不相同则会触发浏览器的保护机制
具体可能会发生的错误
-
Cookie,LocalStorage,IndexDB 等存储性内容无法读取
-
DOM 节点无法访问
-
Ajax 请求发出去了,但是响应被浏览器拦截了
注意: 跨域问题并不是你的Ajax有问题,而是请求发出后,应为不同源浏览器会自动拦截你的响应
此时浏览器会认为你电脑中病毒了或者被其他用户窃取数据,所以会拦截你的Ajax响应.还会报错
解决跨域的方法:
注意:前端解决跨域的最根本便捷的方法就是和后端同学沟通,让后端提供一个支持跨域的接口文档
网上大佬有很多的解决方案,在前端开发过程中,解决跨域也无法从根源上解决问题,但可以在接口文档没有写好的情况下也不影响自己的开发进度,可以使用node.js代理本地服务器解决自己的跨域问题
CORS解决跨域:
目前最简单也是主流的解决跨域的方法(由前后端一起实现)
-
CORS :全称
cross origin resource share
(资源共享) -
工作原理: 服务器 在返回响应报文的时候,在响应头中 设置一个允许的header
-
前端浏览器在IE9以上,后端在响应报头添加Access-Control-Allow-Origin标签,从而允许指定域的站点访问当前域上的资源。
res.setHeader('Access-Control-Allow-Origin', '*');
-
这行代码的工作过程:浏览器请求发送了, 服务器也响应了, 但是浏览器发现了跨域访问, 判断是否有`响应头: Access Control Allow Origin' (后端是否允许跨域访问, 如果允许, 浏览器就把数据留下, 否则抛弃掉然后报错)
//1.导入http模块
const http = require('http')
//2.创建服务器
const app = http.createServer( (req,res)=>{
if( req.url === '/getList' ){
//设置允许跨域响应头
res.setHeader('Access-Control-Allow-Origin', '*');
//响应json字符串
res.end('{"name":"aikun"}')
}
} )
//3.开启服务器
app.listen(3000,()=>{
console.log('服务器启动成功')
})
那有没有前端能完成的跨域解决方案呢???
有的,前端可以使用node.js搭建代理服务器,使用代理服务器发送请求(跨域只对浏览器ajax有限制,对nodejs没有限制)
我们的nodejs服务器就自己设置一个接口
,并设置允许跨域
,把别人服务器的数据响应给浏览器。
.代理服务器工作流程
-
(1)页面 给 代理服务器 发请求
-
(2)代理服务器 给 目标服务器 发请求
-
(3)目标服务器 把 数据响应给代理服务器
-
(4)代理服务器 最后把 数据响应给页面
具体方法:
//1.导入http模块
const http = require('http')
// 导入axios
const axios = require('axios')
//2.创建服务器
const app = http.createServer( (req,res)=>{
if( req.url === '/getList' ){
//设置允许跨域响应头
res.setHeader('Access-Control-Allow-Origin', '*');
//响应json字符串
res.end('{"name":"张三"}')
}else if( req.url === '/getNews' ){
//(1)代理服务器给 目标服务器 发请求
/* 小细节,这个then形参不要叫res,否则会和上面node的响应报文res重名 */
axios.get('http://c.m.163.com/nc/article/headline/T1348647853363/0-40.html').then( result=>{
//(2)设置允许跨域响应头
res.setHeader('Access-Control-Allow-Origin', '*');
//(3)把数据响应给页面 (服务器需要把 对象 转成 JSON 才可以响应)
res.end( JSON.stringify(result.data) )
} )
}
} )
//3.开启服务器
app.listen(3000,()=>{
console.log('服务器启动成功')
})
实际开发过程中(指开发过程,不包括打包上线)
使用vue-cli来解决跨域
- vue-cli脚手架工具在启动时,会开启一个前端项目的服务器。在同一局域网中的用户都可以通过ip地址来访问。
- vue-cli脚手架支持配置一个代理: 将指定的类型请求,转发到目标服务器。
- 代理服务和前端服务之间由于协议域名端口三者统一不存在跨域问题,可以直接发送请求
- 代理服务和后端服务之间由于并不经过浏览器没有同源策略的限制,可以直接发送请求
这样,我们就可以通过服务器代理做接口转发,在开发环境下解决跨域问题,看起来好像挺复杂,其实vue-cli已经为我们内置了该技术,我们只需要按照要求配置一下即可。
首先配置vue.config.js文件
module.exports = {
devServer: {
proxy: {
'/api': { //需要代理的接口
target: 'http://39.98.***.211', //目标服务器
changeOrigin: true, //是否跨域
pathRewrite: { '^/api': 'api' }, //重写
},
},
},
}
其次取消设置axios的 基地址