跨域
跨域,被称为面试官100%、10000%会问的问题
解决跨域的方法有很多,这里详细讲下JSONP,其他方法后续可能也会写文章, 首先 JSONP和 JSON 没有任何关系,就像 Java 与 JavaScript,林允与林允儿
希望大家看完这篇文章,能了解的知识:
- 出现跨域的原因
- 什么时候会出现跨域
- JSONP是如何解决跨域的,有什么缺点
出现跨域的原因:浏览器的同源策略
要了解浏览器的同源策略,我们必须知道一段URL地址的组成
例如: https:// www.baidu.com :8080 /userInfo
其中 https是协议号 —— www.baidu.com 是域名—— :8080是端口 ——/userInfo是路径
当协议号和域名和端口都相同时,才符合同源策略
跨域通常发生在什么时候
是在前端发送请求的时候发生跨域,还是在后端接收到请求,响应请求的时候发生跨域?
我们写段简单代码测试一下
前端代码
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
html
<button id="btn">获取数据</button>
js
let btn = document.querySelector("#btn");
btn.addEventListener("click", function(){
$.ajax({
url:'http://localhost:3000',
data:{name:'yangjun'},
method:'GET',
success(res){
console.log(res);
}
})
},false)
后端代码
const Koa = require('koa')
const app = new Koa()
const main = (ctx,next)=>{
console.log(ctx.query);
ctx.body = 'hello world'
}
app.use(main)
app.listen(3000,()=>{
console.log('项目已启动');
})
当前端发送请求时,因为不符合浏览器的同源策略,会触发跨域
前端显示
后端显示
可以看出来,后端收到了前端发送的请求,但是前端并没有收到后端的响应。
说明跨域发生在后端响应回来的数据,在前端接收的时候被浏览器的跨域机制拦截了下来
解决跨域的方法之——JSONP
1. JSONP思想
JSONP 是一种思想,并不是一个方法, 有些请求是不会受到浏览器的同源策略的影响的。
例如:src、href
<script src=""></script><img src=""><link rel="stylesheet" href="">
JSONP就是利用script 的 src属性加载资源时不受同源策略的影响的这一特性,并且script会将引用的外部文件的文本内容当做js代码来进行解析
2. JSONP实现
前端代码
html
<button id="btn">获取数据</button>
js
const jsonp = (url, params, cb) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
params = { ...params, cb: cb }
const arr = Object.keys(params).map(key => `${key}=${params[key]}`)
script.src = `${url}?${arr.join('&')}`
document.body.appendChild(script)
//后端会返回一个字符串给前端, cb('我今年18岁')
//全局声明一个方法,方法名为cb
window[cb] = (data) => {
resolve(data)
}
})
}
let btn = document.getElementById('btn')
btn.addEventListener('click', () => {
jsonp('http://localhost:3000', { name: '蜗牛', age: 18 }, 'callback').then(res => {
console.log(res)
})
})
后端代码
const Koa = require('koa')
const app = new Koa()
const main = (ctx,next)=>{
//console.log(ctx.query); { name: '我', age: '18', cb: 'callback' }
const {name,age,cb} = ctx.query
const userInfo = `${name}今年${age}岁`
const str = `${cb}(${JSON.stringify(userInfo)})` // 'callback(userInfo)'
//console.log(str); callback("我今年18岁")
ctx.body = str
}
app.use(main)
app.listen(3000,()=>{
console.log('项目已启动');
})
前端显示
后端显示
3. JSONP实现原理
前端在window声明一个方法,此时并没有调用
window[cb] = (data) => {
resolve(data)
}
- 因为script请求的数据,浏览器引擎会直接执行,好比请求的 jquery,引擎会执行这段代码
- 因为script请求的数据,我们没有办法直接操作,或者说请求到的数据我们实际上看不见,但是存在
所以在后端以函数形式返回给前端时,并且前端已经声明过这个函数,函数会直接调用,此时data为后端返回数据
4.JSONP缺点: 只支持get类型请求
在考虑到安全性的时候,不适用,因为get请求携带的参数会在url地址显示
结束了!!!