跨域&解决方案

小小小的学习日记 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搭建代理服务器

借助脚手架搭建服务器



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。