跨域&解决方案
小小小的学习日记 2024-09-11 15:33:09 阅读 89
b站视频链接
跨域&解决方案
浏览器的同源策略
同源策略概述
浏览器为确保资源安全,而遵循的一种策略
什么是源
源的组成部分
源=协议+域名+端口号
下面表格中,只有最后一行的两个源是同源
同源请求与非同源请求
总结:【所处源】与【目标源】不一致,就是【非同源】,又称【异源】或【跨域】
跨域会受到哪些限制
备注:在上述限制中,浏览器限制a ja x获取数据的限制是影响最的的一个,且实际开发中经常遇到
限制DOM访问
<code><body>
<button onclick="showDOM()">showDOM</button>code>
<!-- <iframe id="framePage" src="./demo.html" frameborder="0"></iframe> -->code>
<iframe id="framePage" src="https://www.baidu.com"></iframe>code>
</body>
<script type="text/javascript">code>
function showDOM() {
const framePage = document.getElementById('framePage')
console.log(framePage.contentWindow.document) //同源的可以获取,非同源的无法获取
}
</script>
限制Cookie访问
<body>
<button onclick="showCookie()">showCookie</button>code>
<iframe id="framePage" src="https://www.baidu.com"></iframe>code>
</body>
<script type="text/javascript">code>
function showCookie() {
console.log(document.cookie)
const framePage = document.getElementById('framePage')
console.log(framePage.contentWindow.document.cookie)
}
</script>
限制Ajax获取数据
<body>
<button onclick="getData()">getData</button>code>
</body>
<script type="text/javascript">code>
async function getData() {
const url = 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc'
let result = await fetch(url)
let data = await result.json()
console.log(data)
}
</script>
Access to fetch at 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
几个注意点
跨域限制仅存在浏览器端,服务端不存在跨域限制
即使跨域了,ajax请求也可以正常发出,但相应数据不会交给开发者
<code>link标签、script标签
、img标签
等这些标签发出的请求也可能跨域,只不过浏览器对标签跨域不做严格限制,对开发几乎无影响
CORS解决Ajax跨域方案
CORS概述
CORS全称:Cross-Origin Rresource Sharing(跨域资源共享)
,是用于控制浏览器校验跨域请求的一套规范,服务器依照CORS规范,添加特定响应头来控制浏览器校验,大致规则如下:
服务器明确表示拒绝跨域请求,或没有表示,则浏览器校验不通过服务器明确表示允许跨域请求,则浏览器校验通过
备注:使用CORS解决跨域是最正统的方式,且要求服务器是“自己人”
CORS解决简单请求跨域
整体思路:服务器在给出响应时,通过添加Access-Control-Allow-Origin
响应头,来明确表达允许某个源发起跨域请求,随后浏览器在校验时,直接通过
请求代码
<code><body>
<button onclick="getData()">getData</button>code>
</body>
<script type="text/javascript">code>
async function getData() {
const url = 'http://127.0.0.1:8081/students'
let result = await fetch(url)
let data = await result.json()
console.log(data)
}
</script>
服务器代码(以express框架为例)
const express = require('express')
const app = express()
const students = [
{
id: 1,
name: 'st1'
},
{
id: 2,
name: 'st2'
},
{
id: 3,
name: 'st3'
}
]
app.get('/students', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
res.send(students)
})
// 启动服务器
app.listen('8081', () => {
console.log(`Server is running at http://127.0.0.1:8081`)
})
简单请求与复杂请求
CORS会把请求分为两类,分别是 简单请求、复杂请求
CORS解决复杂请求跨域
第一步:服务器先通过浏览器的预检请求,服务器需要返回如下响应头
第二步:处理实际的跨域请求(与处理简单请求跨域的方式相同)
请求代码:
<code><body>
<button onclick="getData()">getData</button>code>
</body>
<script type="text/javascript">code>
async function getData() {
const url = 'http://127.0.0.1:8081/students'
let result = await fetch(url, {
method: 'GET',
headers: {
name: 'ym',
age: 120
}
})
let data = await result.json()
console.log(data)
}
</script>
服务端代码:
const express = require('express')
const app = express()
const students = [
{
id: 1,
name: 'st1'
},
{
id: 2,
name: 'st2'
},
{
id: 3,
name: 'st3'
}
]
app.options('/students', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
res.setHeader('Access-Control-Allow-Method', 'GET')
res.setHeader('Access-Control-Allow-Headers', 'name,age')
res.setHeader('Access-Control-Max-Age', 7200)
res.send()
})
app.get('/students', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
res.send(students)
})
// 启动服务器
app.listen('8081', () => {
console.log(`Server is running at http://127.0.0.1:8081`)
})
借助cors库快速完成配置
上述的配置需要自己配置响应头,或者需要自己手动封装中间件,借助cors库,可以更方便完成配置
安装cors
npm i cors
简单配置cors
app.use(cors())
完整配置cors
const corOptions = {
origin: 'http://127.0.0.1:5500', //允许的源
methods: ['get', 'post', 'put', 'delete', 'head', 'options'], //允许的方法
allowHeaders: ['name', 'age'], //允许的自定义头
exposedHeaders: ['age'], //要暴露的响应头
optionsSuccessStatus: 200 //预检请求成功的状态码
}
app.use(cors(corOptions))
JSONP解决跨域问题
JSONP概述:JSONP是利用script标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持CORS的时候,可以靠JSONP解决跨域
基本流程
客户端创建一个script标签,并将其src属性设置为包含跨域请求的url。同时准备一个回调函数,这个回调函数用于处理返回的数据服务端接收到请求后,将数据封装在回调函数中并返回客户端的回调函数被调用,数据以参数的形式传入回调函数
图示
代码示例
<code><body>
<button onclick="getData()">getData</button>code>
</body>
<script type="text/javascript">code>
function test(data) {
console.log(data)
}
function getData() {
const script = document.createElement('script')
script.src = 'http://127.0.0.1:8081/students?callback=test'
document.body.appendChild(script)
script.onload = () => {
script.remove()
}
}
</script>
app.get('/students', (req, res) => {
const { callback } = req.query
res.send(`${callback}(${JSON.stringify(students)})`)
})
jQuery封装的jsonp
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>code>
<script type="text/javascript">code>
$.getJSON('http://127.0.0.1:8081/students?callback=?', data => {
console.log(data)
})
</script>
配置代理解决跨域
自己配置代理服务器
借助http-proxy-middleware
使用ngin x搭建代理服务器
借助脚手架搭建服务器
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。