您的位置:首页 > 财经 > 产业 > 国际新闻最新消息今天新冠肺炎_如何推广qq群_搜索引擎平台_引擎优化seo怎么做

国际新闻最新消息今天新冠肺炎_如何推广qq群_搜索引擎平台_引擎优化seo怎么做

2025/4/19 8:15:43 来源:https://blog.csdn.net/2202_75396973/article/details/147262144  浏览:    关键词:国际新闻最新消息今天新冠肺炎_如何推广qq群_搜索引擎平台_引擎优化seo怎么做
国际新闻最新消息今天新冠肺炎_如何推广qq群_搜索引擎平台_引擎优化seo怎么做

同源策略

同源策略是浏览器中一个核心的功能,主要与安全相关

主要内容是:同协议、同域名、同端口,三者相同才是同源,否则会出现跨域问题

比如:在web端,需要在服务端请求接口来获取当前页面数据,访问后端时,一般情况下后端会给一个请求地址,通常这个地址与前端的是不一样的,这时就会出现跨域问题,这样我们就拿不到我们想要的数据。

但是这样也有优势,因为这样安全系数比较高:

比如:在浏览器中写一个iframe,iframe能够直接访问到外部窗口和外部网站的资源,如果没有同源策略,我们就可以直接访问和获取到其他网站的数据和资源,这样就不安全了。

同源策略极大的提高了网站数据的安全性,同时在请求后端接口时、发送ajax请求时不太方便

复现跨域问题

1、通过axios库发送请求

在html的body标签中写

<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.8.4/axios.min.js"></script>

2、引用axios的属性(body标签)

axios({methods:'get',url:'后端提供的接口'
})

我们需要用后端模拟这个接口

  • 在当前项目中创建一个node目录
  • 右键该目录,打开命令行,然后cd node到该目录下
  • 在这个node目录下搭建后端服务:我们需要用到express,我们需要下载这个依赖,于是我们要初始化一个package.json,我们通过npm init的方式来下载,回车后等待;弹出的属性我们使用默认信息
  • 完成后会在node目录下出现一个package.json的文件,有了这个文件,就可以下载依赖,继续在命令行输入:npm i express,然后回车
  • express可以理解为是基于node的后端的脚手架,可以基于express来快速搭建后端的服务,下载完成后,在node目录下会多一个node.modules的目录,这是依赖;同时还多了一个package-lock.json的文件,这相当于是包的版本控制
  • 在node目录下创建一个index.js文件,关于后端的就写在这里
// 引入express
const express = require('express')

在node环境里面,通过require来引入express依赖

// 创建实例
const app = express()

调用express方法,会返回一个对象

// 创建一个监听的端口
const port = 3000
// 定义接口
app.get('/api/getData',(req,res)=>{// 返回的结果res.send({code:10000,// 状态码data:{msg:'hello world'}})
})
  • express创建接口之所以简单,是因为能直接用调用它的属性和方法
  • 我们定义一个get接口,只用通过对象来点get这个方法,接收两个参数:第一个是接口的请求你路径,第二个是一个回调函数,接收请求的结果
  • 回调函数有两个参数:第一个是请求体req,第二个是响应体res
  • 当我们调用定义的接口,就用res点send方法来返回相关信息,一般后端会以一个json对象的形式返回,这个json中一般会定义几个字段如:code表示后端返回的状态码,这里用10000来表示正常的结果,data表示数据,我们定义了一个msg的属性,

接口定义结束,如果要后端开始生效,需要对端口进行监听

// 监听当前端口
app.listen(port,()=>{console.log('server start! port:${port}')// 这里用了模板字符串的语法${}
})
  • 通过listen方法来监听,有两个参数,一个是端口号,一个是回调函数,回调函数执行监听完成后做的事,这里就是输出一句话和输出端口号

都完成后需要启动node服务,在刚刚的命令行(node目录下)输入node index.js来执行,查看返回的信息可以知道是否能够运行起来

对于get接口,我们可以直接用浏览器来访问:localhost:端口号加上get端口的地址,即可在浏览器中看到返回的信息(接口创建成功)

回到刚才使用axios的前端代码(body标签)

axios({methods:'get',url:'http://localhost:3000/api/getData',// http://127.0.0.1是本地的ip// 3000是端口号// 后面的就是刚刚在后端定义的地址
})

定义完成后,我们需要将这个html文件通过服务器的方式启动

要么使用阿帕奇等方式,要么就用vscode的插件(preview on web Server)来启动,下载好后,右键html文件,在下方有“vscode-preview-server:Launch on browser”,点击后稍等一下就会在浏览器中访问一个叫8080的端口(localhost:8080),其实就是访问html这个文件所在的根目录,然后点击里面的html文件,这样就是以服务器的方式启动本地的html文件

在前后端链条时,需要在服务器的环境下执行,不然会报错

运行完后,f12,打开Network查看网络请求,可以在all中看到所有请求,转去Fetch/XHR中查看,可以看到getData有一个CORS error的错误,回到控制台,也可以看到一条报错是:从服务端发出的接口地址没有在请求的资源中找到,也就是地址不同,也就是当前的请求发生了跨域问题。

网络请求的路径

由上面的例子:http://localhost:3000/api/getData

  • http是协议
  • localhost是域名
  • 3000和上面提到的8080是端口号
  • /api/getData是请求的路径
  • 有的网址后面还有请求参数、链点

1、https是加密协议

2、ip与域名有映射关系,是绑定的,如:www.baidu.com和163.177.151.109,但是即使是映射关系,但是写法不同,还是会出现跨域问题

3、默认端口可以省略(http默认80,https默认443),只是这种的话不会触发跨域问题

localhost与127.0.0.1的区别
localhost127.0.0.1本机IP
网络不联网不联网联网
传输不使用网卡,不受防火墙和网卡限制网卡传输,受防火墙和网卡限制网卡传输,受防火墙和网卡限制
访问本机访问本机访问本机访问

跨域问题下,并非所有资源都无法访问

在跨域网络访问中,跨域资源的嵌入,如我们前面代码中引用的cdnjs的地址,就是属于跨域资源的嵌入,是可以访问到的,所以有这样的结论,

凡是从外部引入的资源,都属于跨域网络访问中的跨域资源的嵌入式操作,这种网络访问不存在跨域问题

还有就是跨域写操作,比如在a标签中写上一个地址,点击a标签时的跳转不会发生跨域问题

跨域的读操作(ajax异步请求),就要遵循同源策略,不然就有跨域问题

那么怎解决跨域问题呢?

JSONP解决同源限制问题

原理:利用script标签的src属性可以跨域加载资源的特性,通过动态创建script标签来实现跨域请求。

跨源网络访问的三种方式:跨域写操作,跨域资源嵌入,跨域读操作

访问刚才后端的端口地址

<script src="http://localhost:3000/api/getData?cb=callback"</script>
<script>// 要在这里定义一个回调函数function callback(){}    
</script>

如果我们只是单纯的引入后端的端口地址,我们是拿不到响应的,所以我们要传一个参数,而且必须是一个回调函数,因为我们采用的是script标签的src属性来访问当前资源。想要拿到响应,需要传一个函数到后端,后端通过返回这个函数的调用,从而把数据传回来

传入参数后,就可以把请求发给后端,后端通过参数cb拿到callback函数,把数据返回回来,但是这样写就是写死了script标签。如果我们要用这种jsonp方式,更多是要动态创建:

// 动态创建script标签
const script = document.createElement('script')
// 设置src属性
script.src = 'http://localhost:3000/api/getData?cb=callback'
// 接收后端的回调函数
function callback(res){console.log(res)
}
// 把script挂载在页面上
document.getElementsByTagName('body')[0].appendChild(script)

以上是前端的代码,但是后端也需要改代码:

我们需要获取前端的回调函数传过来的参数:

// 创建一个监听的端口
const port = 3000
// 定义接口
app.get('/api/getData',(req,res)=>{// 获取前端参数const {cb} = req.queryres.send('${cb}(${JSON.stringify({code:10000,// 状态码data:{msg:'hello world'}})})')
})
  • // 获取前端参数 const {cb} = req.query,通过query来获取所有参数
  • res.send,发送响应的信息给前端,不能直接传cb(),这样前端接收不到,所以需要对这个对象做一个序列化处理,调用JSON.stringify的方法
  • 重启后端

前后端修改后重启,会发现,在原先的网络请求页面的异步任务选项中看不到刚才的请求getData,但是all中能找到,而且其标签也是script,所以说这个请求能访问到后端是利用了script标签没有跨域问题的这个特性。

弊端:

  • 一定要在地址后面传一个函数参数过去
  • 请求类型只能是get请求(script标签的src属性发送到只能是get请求),类型被限制
  • 有安全隐患,后端容易受到注入攻击

CORS(跨域资源共享)(主流方法)

浏览器提供的跨域的解决方案

原理:需要服务器实现CORS接口,在服务器端设置响应头,允许指定的域名访问资源。

在服务端实现cors接口,在服务端的响应头添加标识,当浏览器接收到这个标识时,默认当前这个请求没有跨域问题

这个需要在后端修改,在创建端口代码下面添加

app.all('*',(req,res,next)=>{res.header('Access-Control-Allow-Origin', '*') //允许所有的请求源res.header('Access-Control-Allow-Headers', '*') //允许所有的请求源 X-Tokenres.header('Access-Control-Allow-Methods', '*') //允许所有的请求源 get post put deletenext();
})
  • 需要用点all这个api,点all指的是所有的接口
  • 第一个参数是’*',表示匹配所有类型接口任意的路径。
  • 第二个参数是一个回调函数,回调函数的参数有三个:请求体、响应体、next,只有next被调用了代码才会往下走
  • res.header('Access-Control-Allow-Origin', '*') //允许所有的请求源,这一句代码的意思是:在响应头里添加/允许请求的请求源’*',这里的请求源其实是一个ip地址;比如想要限制对应的ip,就可以把星号改为一些服务器上的一些地址,如果所有的都可以访问,就可以上星号(通配符)
  • 第二句的意思是:允许的请求头,比如前端会在请求头中添加一些参数,如果只允许token访问,就在星号处换成token,也就把能够接收这些请求头里面的数据,都要写在里面
  • 第三句的意思是:请求的类型,类型包含:get、post、put、delete,星号就是都允许,默认所有都支持
  • 调用next(),next要调用,不调用的话,后续代码不会执行

重启后端代码,然后前端代码用回之前res.send的代码而不是修改为jsonp的形式,重启代码并运行,就可以解决跨域问题

补充:

  • 在上面的cors的例子中,可以发现只发了一个请求,有的时候会遇到多个请求的情况,也就是同一个接口会有多个请求,下面来复现一下
// 修改前端的代码
axios({methods:'get',url:'http://localhost:3000/api/getData'// 添加一个头headers:{token:1}
})

重新启动一下,在浏览器中可以看到,名为getData的请求出现了两次,而且两次的类型不同(preflight,xhr),类型为preflight的请求,它的请求类型是options,也就是预检。预检就是:对于刚才的post请求而言,如果给其添加了自定义的头的话,那么在发起请求时,会首先发起一个options请求到后端,只有后端通过后,才会发起第二个请求,也就是get请求来请求真正的数据。总的来说就是:如果有携带自定义的headers参数的话,就会发起预检。这一类的请求也称为非简单请求。如果以后出现有两次请求的情况,可以考虑一下是发送的预检,而并非调用两次

代理服务器

原理:在同源策略下,通过在同一域名下设置代理服务器,将跨域请求转发到目标服务器上。

同源策略仅限于浏览器与服务器之间,服务器与服务器之间没有跨域问题。

通过vue框架来举例:

1、在终端中,用cli来创建vue:

  • 安装脚手架:npm i @vue/cli -g,如果安装了的,可以用vue -V来查看版本
  • 创建项目:vue create app,语法:vue create 项目名称
  • 选择模板,等待下载依赖

2、下载好后,左上角会有出现安装好的app文件夹

  • 在终端中cd到app目录,与之前一样,在这个项目中实现前后端的联调
  • 下载axios(用模块化的方式下载):npm i axios
  • 下载后在项目中找app.vue文件,有的话就可以在终端中运行一下:npm run serve

3、修改App.vue文件中的script标签中的代码:

// 引入axios模块
import axios from 'axios'
// name属性下面添加
mounted(){axios({url:'http://127.0.0.1:3000/api/getData'})
}

运行一下可以方面是可以请求到接口的,因为前面的部分我们对后端做了可跨域处理,把后端的cors的处理注释掉,又会报错

如何解决?找到当前项目的vue.config.js文件(项目配置文件),修改代码

// module.expoets中添加
devServer:{proxy:{'/api':{ // 配一个key,用于匹配所有路径中有/api的接口target:'http://127.0.0.1:3000' // 匹配到之后,代理到目标地址target}}
}
  • devServer指的是本地服务器,用这个就是在本地的服务器中配置对应的ip地址、端口等,这里重点讲代理(proxy)

  • 删去前端中路径的前半段’http://127.0.0.1:3000’,不修改的话还会报错,因为写死了端口号

  • 修改后,重启项目:npm run serve

  • 在浏览器中可以看到getData请求中的url地址的变成当前前端的地址,这样api就可以被代理服务器代理到,然后有服务器进行转发

这种代理,仅限本地开发,这种方式是由前端来做处理。但是利用框架,如果想要把项目进行上线,需要对项目进行打包,打包的话,本地的代理就会失效,最后发布后,还是要通过服务器来解决跨域问题

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com