目录
1.跨域报错
跨域会报一个固定格式的错误:
Access to XMLHttpRequest at 'ajax请求地址' has been blocked by CORS policy: No '网页请求地址' 'Access-Control-Allow-Or' present on the requested resource;
2.跨域现象产生的原因
- ajax请求地址与页面请求地址不同源!
- 跨域只会出现在ajax请求,若是href、src是不会出现跨域问题的!
- ajax地址:获取数据的请求;
- 页面请求地址:window.location.href;
- 同源策略:若是协议、端口号、ip地址(域名) 全部一致被称为同源;
- 也就是说只要是协议、端口号、域名任何一个不一致则被称为不同源!
- eg:页面地址为 http://127.0.0.1:3000/hero/add
- ajax地址:https://127.0.0.1:3000/hero/all ---不同源(协议名不一致)
- ajax地址:http://179.0.0.1:3000/hero/all ---不同源(域名不一致)
- ajax地址:http://179.0.0.1:4399/hero/all ---不同源(端口号不一致)
- ajax地址:https://127.0.0.1:3000/hero/add ---同源(与url路经无关)
[1].为什么要有同源策略?
其实同源策略存在的原因是浏览器为了保护电脑的安全:当ajax地址与页面请求地址不一样时,浏览器会认为你在向两台不同的服务器发送请求;此时浏览器会认为这个是不安全的,会将请求拦截。
3.如何解决跨域?
[1]CORS解决跨域(后端设置)
(1)后端设置白名单,也就是在响应头中设置一个标识,表示这个请求允许跨域;
(2)工作原理: 服务器 在返回响应报文的时候,在响应头中 设置一个允许的header
res.setHeader('Access-Control-Allow-Origin', '*');
这样这个ajax网址在发送请求的时候就不会出现跨域问题了!
(3)node中使用:因为存在多个请求,若是我们设置的话很麻烦而且会产生代码冗余;
解决:使用中间件在响应头的原型上添加允许跨域的属性setHeader;这样所有的请求(即使使用本地路经)都不会产生跨域问题了!
// 4.4允许跨域的中间件
const cors = require('cors')
app.use(cors())
// 原理给req的原型添加seHeader方法;
[2]JSPN解决跨域(前端+后端设置)
jsonp是早期解决跨域的方案;
(1)使用原理:浏览器漏洞
- [1]跨域只存在于ajax请求,src是不会产生跨域的;
- [2]如果script的src请求,服务器响应的数据是一个函数的调用,则浏览器会检查页面中是否存在此函数;
- 页面中存在---调用;
- 页面中不存在--报错 function is not defined
(2)项目中使用的工作流程
- (1)在发送ajax请求的时候使用script标签的src属性来发送;
- (2)在原有的参数后面追加一个参数 callback
- 参数值为页面中声明的函数名;
- (3)服务器返回一个函数的调用即可;
- 举例说明(原生js)
- [1]写一个html页面--发送请求的时候使用script标签的src属性
-
<body> <script> function success (results) { console.log(results) } </script> <script src="http://127.0.0.1:3000/add?id=5&callback=success"></script> </body>
- [2]使用node搭建服务器--若是url为/add,返回一个函数的调用,此时浏览器会去查找页面中是否有success方法,如是有的话则调用此函数;
- 此时页面打印666
-
const express = require('express') const app = express() // 路由 app.get('/add', (req, res) => { console.log(req.url) let { callback } = req.query // 假设响应结果为person对象 let person = { name: 'chaochao', age: 20 } res.end(`${callback}(${JSON.stringify(person)})`) }) app.post('/add', (req, res) => { console.log(req.url) res.end('success()') }) app.listen(3000, () => { console.log('服务器开启成功') })
- 举例说明(jquery)
-
$.ajax({ url:'http://127.0.0.1:3000/add', dataType:'jsonp', data:{id:5}, success:function(backData){ conslole.log(backData) } })
- 原理:jq在想使用jsonp时只需要将dataType的属性值由json变为jsonp即可;
- 在发送请求的时候,jq会动态的在head中创建一个script标签用来发送请求;
- 发送请求之后服务器返回success的调用;
- 服务器响应数据之后,jq会自动删除创建的script标签;
-
[3]使用代理来解决跨域(前端)
-
执行原理:
-
因为跨域是在
客户端与服务端产生的跨域
,也就是说在服务端与服务端之间是不会产生跨域的; -
所以
-
[1]向浏览器同源的服务器发送请求;
-
[2]同源服务器再向实际不同源的服务器发送请求
-
-
经过转换,就不会产生跨域问题了;
-
-
使用场景
-
只适用于开发环境,生产环境是没有办法使用的!
-
-
代码
-
//vue-cli3.0 里面的 vue.config.js做配置 module.exports = { devServer: { proxy: { '/public': { //这里最好有一个 / target: 'http://127.0.0.1/heimamm/public', // 后台接口域名 secure: false, // 如果是https接口,需要配置这个参数 changeOrigin: true, //是否跨域 pathRewrite: { '/public': '' } } } } } // 只要碰到以/public开头的基地址,在发送请求时都会将基地址转化为target属性值+‘/public’ //使用pathRewrite属性是将拼接的/public转化为空 //注:在使用的时候将.env.development配置文件中的基地址换为/public
-