同源策略
由Netscape公司引入浏览器。目前,所有浏览器都实行这个政策。
目的是为了保证用户信息的安全,防止恶意的网站窃取数据
若非同源,会有三种行为限制:
1、Cookie、LocalStorage和indexDB无法读取
2、DOM无法获得
3、AJAX请求不能发送
同源指的是:协议相同、域名相同、以及端口相同。
互联网默认原则(不允许跨域访问)
常见跨域
HTML 页面中一些允许指定路径的元素具有跨域特性:
<link>元素
<script>元素
<img>元素
<iframe>元素
解决跨域
CORS(后端操作)
跨域是前端工作中不可避免的问题:我们经常会出现请求不同源接口的情况,为了能够获取数据,解决跨域的问题方案也有很多,但是常用的就两种
■第一种: CORS(后端操作)
目前的主流方案,也是最简单的方案,直接让后端设置响应头,允许资源共享就ok.
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
例如:
app.get('/login',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*')
})
解决跨域问题,设置响应头的代码,可以在中间件中写,这样可以在所有接口中都会应用到(只在中间件写一次就可以了,不用再多个接口中去写,因为中间件是在服务器开启之后和路由响应之前执行的一个函数)
例如:
app.use((req,res,next)=>{
res.setHeader('Access-Control-Allow-Origin','*')
next()
})
-------------------------------------------------------------------------------------
或者还可以安装第三方模块(npm i cors)
例如:
const cors=require('cors')
app.use(cors());
JSONP(前后端配合)
■第二种:JSONP(前后端配合)
曾经的跨域杀手,专治各种跨域问题。现在慢慢的淡出历史舞台
PS:面试官特别喜欢问这个,因为这个有一定的技术难度,也能体现一个人的实际开发经验
jsonp是前后端来配合使用的.
使用原理:通过动态创建script标签通过script标签的src请求没有跨域限制来获取资源
补充知识:
浏览器页面上使用ajax发请求,当前页面地址和ajax请求的地址不同源,才会有跨域限制
但script、img、link标签中的src属性发的请求都没有跨域限制
使用jsonp原理:
这样便可以用script标签中的src来操作,去访问后端地址的接口时,前后端规定好使用的get请求传入的参数名便可,这样也没有了跨域限制
-----------------------------------------------------------------------------------------
前端页面,例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSONP</title>
</head>
<body>
<script>
function print(obj){
alert(obj.user)
alert(obj.data)
}
</script>
<!-- 前端页面:访问后端API,传入后端指定get参数,后端处理返回后,接受到返回的调用和实参对象来使用 -->
<script src="http://127.0.0.1:8888/getAll?fun=print"></script>
</body>
</html>
-----------------------------------------------------------------------------------------
后端页面,例如:
const express=require("express")
const app=express()
app.get('/getAll',(req,res)=>{
res.send(`${req.query.fun}({"user":"我是jine","data":"成功调用√"})`)
})
app.listen(8888,()=>{
console.log("服务器成功启动√")
})
或者还可以直接在Ajax请求时,加上 dataType:'jsonp'
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>点击哟</title>
<script src="https://jine.oss-cn-beijing.aliyuncs.com/API/jquery-3.5.0.js"></script>
<script>
$(()=>{
let $btn= $('button')
$btn.on("click",()=>{
$.ajax({
url:'http://127.0.0.1:8888/getAll',
dataType:'jsonp',
success:(backData)=>{
alert(backData.user)
alert(backData.data)
}
})
})
})
</script>
</head>
<body>
<button>点击我哟~</button>
</body>
</html>
"注意:后端中的参数必须是callback,因为使用ajax开启jsonp,src传递的参数是callback,所以要一致"
或者用jQuery中的$.getJSON()方法允许通过使用JSONP形式的回调函数来加载其他网域的JSON数据
$.getJSON('http://127.0.0.1:8080?callback=?',(data)=>{
console.log(data)
})
"注意:$.getJSON()方法的一个参数表示url,需要在该参数后面添加 callback=? 。jQuery将? 自动替换为正确的函数名,以执行回调函数