1.跨域
1.1-跨域固定报错格式
只要是出现跨域问题,浏览器就会出现一个固定格式(没有之一)的报错信息
Access to XMLHttpRequest at '服务器url地址' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
注意 : 跨域一定是这个问题,但出现这个问题不一定是跨域
1.2-什么是跨域?
-
浏览器使用
ajax时,如果请求了的**接口地址** 和 当前**打开的页面** 地址不同源称之为跨域- (1)ajax : 浏览器只有使用ajax发送请求才会出现跨域。 href属性与src属性不会出现跨域
- (2) 接口地址 : ajax请求的url
- (3)打开的页面:当前页面的window.location.href
- (4)不同源 : 浏览器使用ajax,向不同源的接口发送请求,称之为 跨域访问
1.3-什么是同源?
-
MDN官方文档传送门:developer.mozilla.org/zh-CN/docs/…
-
同源定义 : 两个url地址的
协议与主机与端口均一致 (&&)- 协议:http , https , file
- 主机 : 域名或者ip地址 (127.0.0.1)
- 端口 :3000, 4399
-
不同源定义: 两个url地址,
协议 主机 端口任何一个不一致 (||)http:127.0.0.1:3000/abchttp:127.0.0.1:3000/efghttps:127.0.0.1:3000/efghttp:127.0.0.1:3000/hero/addhttp:127.0.0.1:4399/hero/addhttp:127.0.0.1:4399/hero/all
1.4-为什么要有同源与不同源?
-
出于安全考虑,浏览器不允许,页面向不同源的接口请求数据,因为如果 接口 和 网页不同源,浏览器认为是2个不同的 服务器,
-
不同的服务器中内容是不可控的,不允许访问了
-
总结说人话:
浏览器为了保护你的电脑安全 -
举个栗子: 你去肯德基店里点餐,店员只允许你点肯德基的产品(炸鸡,可乐,上校鸡块),如果此时你在肯德基店里面点麦当劳的产品,浏览器会认为你是坏人,就会让保安把你赶出去
1.5-跨域解决方案介绍
-
跨域是前端工作中不可避免的问题:我们经常会出现请求不同源接口的情况,为了能够获取数据,解决跨域的问题方案也有很多,但是常用的就两种
-
第一种 :
CORS -
目前的主流方案,也是最简单的方案
-
第二种:
JSONP- 曾经的跨域杀手,专治各种跨域问题。现在慢慢的淡出历史舞台
- PS:面试官特别喜欢问这个,因为这个有一定的技术难度,也能体现一个人的实际开发经验
1.6-示例
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<a href="http://127.0.0.1:3000/abc">点我发请求</a>
<br>
<button>点我发请求</button>
<script>
document.querySelector('button').addEventListener('click', function () {
//(1).实例化ajax对象
let xhr = new XMLHttpRequest()
//(2).设置请求方法和地址
//get请求的数据直接添加在url的后面 格式是 url?key=value
xhr.open('get', 'http://127.0.0.1:3000/abc')
//(3).发送请求
xhr.send()
//(4).注册回调函数
xhr.onload = function () {
console.log(xhr.responseText)
}
})
</script>
</body>
</html>
服务器
//1.导入模块
const express = require('express')
//2.创建服务器
/* express() 相当于http模块的http.createServer() */
const app = express()
//3.接收客户端请求
app.get('/abc',(req,res)=>{
//响应客户端数据
res.send({
status:200,
msg:'请求成功',
data:{name:'张三',age:20}
})
})
//4.开启服务器
app.listen(3000,()=>{
console.log('服务器启动成功')
})
2.跨域解决方案
2.1-跨域解决方案一: CORS
2.1.1-CORS工作原理介绍
-
CORS :全称
cross origin resource share(资源共享) -
工作原理: 服务器 在返回响应报文的时候,在响应头中 设置一个允许的header
res.setHeader('Access-Control-Allow-Origin', '*');
2-express使用中间件cors : 给所有的res添加默认请求头Access-Control-Allow-Origin
-
express有一个自带的中间件cors,它的作用是自动给每一个res设置默认请求头
- 这样就不用我们自己每一个接口都要设置一次了
- 用法介绍
- cors中间件是最简单的中间,底层原理如下
app.use((req, res, next) => {//任何请求都会进入这个use中间件
res.setHeader('Access-Control-Allow-Origin', '*')//设置响应头
next()//执行下一个中间件
})
2.2-跨域解决方案二:原生jsonp
-
了解jsonp原理,首先一定要明白script标签的src属性做了什么事情-
(1)scr属性会给服务器发送请求, 请求一个js文件
-
(2)浏览器会解析执行这个js文件里面的代码
- 如果浏览器直接返回js代码,浏览器会立即执行
-
-
1.JSONP的核心原理:如果script标签的src属性的请求,服务器返回的是一个函数调用。则浏览器会执行这个函数
- 这是浏览器script标签的一个的漏洞(历史遗留问题)
-
2.实际开发中JSONP的工作流程
-
(1)设置script标签的src属性,向一个不同源的接口发送一个get请求
- JSONP只支持get请求,不支持post
-
(2)src属性发送请求时,在参数中额外携带一个callback的参数,参数值是一个在页面中预先定于好的函数名
-
callback : 这是发明jsonp技术的人提出的一个
君子之约,只要是jsonp前端程序员都统一将参数名定义为callback- PS:别的参数也行,只要和服务器协商好
-
callback属性值:预先定义的函数名,这个函数必须要在script标签之前定义
-
-
(3)服务器接收到请求之后,获取callback的参数值
-
(4)服务器将要响应的数据拼接成
函数调用格式,通过传参的方式将响应数据返回给浏览器
-
-
3.JSONP与CORS区别
-
CORS:
- 服务器返回响应头,前端无需任何处理
- 简单快捷,支持所有请求方式
-
JSONP
-
浏览器:自定义响应回调函数,使用script标签的src请求
- 利用浏览器的src属性没有跨域这一限制特点
-
服务器:接收callback参数,返回函数调用
-
处理复杂,并且只支持get请求
- 原因:get请求参数直接在url后面拼接,而post请求参数是放在请求体中
-
-