IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> http协议(二)CORS跨域限制以及预请求验证 -> 正文阅读

[网络协议]http协议(二)CORS跨域限制以及预请求验证

1. Request.mode

Request 接口的 mode 只读属性包含请求的模式(例如:cors 、 no-cors 、 cors-with-forced-preflight 、 same-origin 或 navigate 。)这用于确定跨域请求是否能得到有效的响应,以及响应的哪些属性是可读的。

属性值作用
same-origin如果使用此模式向另外一个源发送请求,显而易见,结果会是一个错误。你可以设置该模式以确保请求总是向当前的源发起的。
no-cors保证请求对应的 method 只有 HEAD,GET 或 POST 方法,并且请求的 headers 只能有简单请求头,时保证了在跨域时不会发生安全和隐私泄露的问题。
cors允许跨域请求,例如访问第三方供应商提供的各种 API。
navigate表示这是一个浏览器的页面切换请求(request)。 navigate请求仅在浏览器切换页面时创建,该请求应该返回HTML。

当一个 Request 对象以 Request.Request 方式创建,该Request 的 mode 的值为 cors
然而,除了以 Request.Request 创建的请求,模式通常为 no-cors 。例如,对与嵌入资源发起的请求,除非存在 crossorigin 属性,即对于 <link> 、 <script> (除了和模块一起使用之外)、 <img>、 <audio>、 <video>、 <object>、 <embed>还有 <iframe> 元素,在大多数情况下是使用 no-cors 模式。

也就是说,之所以JSONP可以通过<script>标签来实现跨域,就是因为<script>标签发起的请求使用了mode:'no-cors'

server.js: 监听8888端口,返回一个index.html,index.html向8887端口发起请求。

const http = require('http')
const fs = require('fs')

http.createServer(function (request, response){
  console.log('request url: ', request.url)

  const html = fs.readFileSync('index.html', 'utf-8')
  response.writeHead(200, {
    'Content-Type': 'text/html'
  })
  response.end(html)
}).listen(8888)

console.log('server running on 8888')

index.html: 向8887端口发起跨域请求

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div>content</div>
</body>
<script>
  fetch('http://localhost:8887', {
    method: 'POST',
    mode: 'no-cors'
  })
</script>
</html>

server2.js: 监听8887端口

const http = require('http')

http.createServer(function (request,response){
  console.log('request url: ', request.url)
  response.writeHead(200, {
    // 'Access-Control-Allow-Origin': 'http://127.0.0.1:8888'
  })
  response.end('123')
}).listen(8887)

console.log('server running on 8887')

注意:我们并没有在8887端口设置’Access-Control-Allow-Origin’: ‘http://127.0.0.1:8888’,而是在index.html发起请求时设置了mode: ‘no-cors’
请求成功返回数据:
在这里插入图片描述

2. CORS跨域限制

为了发起PUT,DELETE等非简单请求,甚至自定义请求头,如何正确的跨域呢?
这时候就不能简单的使用mode:'no-cors'来应对了。

2.1 发起PUT请求

我们修改server2.js,使来自8888端口的请求能正常返回数据。

  response.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://127.0.0.1:8888'
  })

修改index.html,发起PUT请求:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div>content</div>
</body>
<script>
  fetch('http://127.0.0.1:8887', {
    method: 'POST',
    mode: 'no-cors'
  })
</script>
</html>

控制台报错:
在这里插入图片描述
值得我们注意的是,网络中不止一个put请求被客户端发送到8887端口:
在这里插入图片描述
在这里插入图片描述
我们明明是向127.0.0.1:8887发送了PUT请求,为什么这里多出来了一个OPTIONS请求呢,后文中会有详细的解释。
根据控制台的报错信息,我们修改server2.js:

  response.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://127.0.0.1:8888',
    'Access-Control-Allow-Methods': 'PUT'
  })

然后重新访问,控制台就没有报错信息了,并且成功拿到了8887端口返回的数据,但是,此时的网络还是存在一个OPTIONS的请求。

2.2 自定义表头

修改index.html:

<script>
  fetch('http://127.0.0.1:8887', {
    method: 'POST',
    headers: {
      'My-Custom-Header': 'Test'
    }
  })
</script>

重新访问,控制台报错:
在这里插入图片描述
这时候,我们由于设置了自定义表头,我们还需要在8887响应头中设置Access-Control-Allow-Headers
修改server2.js:

  response.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://127.0.0.1:8888',
    'Access-Control-Allow-Headers': 'My-Custom-Header'
  })

重新访问,控制台不在报错,同样的,这时候网络中也增加了一个OPTIONS的请求。

3. 预请求验证

这里的预请求验证就是前文中我们发现的OPTIONS请求。
什么时候会发送OPTIONS请求呢?
当一个请求(记做R)跨域并且不是简单请求的时候,浏览器会先向请求目标发送一个OPTIONS请求,通过OPTIONS请求判断是否发送请求R。
预请求验证可以避免跨域请求对服务器数据产生不可预料的影响,使跨域请求更加安全。
怎样的请求才是简单请求呢?
请求方法: 只能是一下三种之一

  1. GET
  2. HEAD
  3. POST

Content-Type: 只能是以下三种之一

  1. test/plain
  2. multipart/form-data
  3. application/x-www-form-urlencoded

每当发送一个非简单请求时,浏览器都会发送一个OPTIONS请求,如果我们需要频繁的发起类似请求,那么就会增加我们的网络负担,所以,我们可以修改server2.js:

  response.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://127.0.0.1:8888',
    'Access-Control-Allow-Headers': 'My-Custom-Header',
    'Access-Control-Max-Age': 1000
  })

当我们第一次发起请求时,浏览器会发送OPTIONS请求:
在这里插入图片描述
在之后的'Access-Control-Max-Age'时间内,浏览器都不需要再次发送OPTIONS请求。
在这里插入图片描述

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:30:49  更:2022-03-21 21:32:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:35:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码