Jacky's blog Jacky's blog
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Jacky Wang

行到水穷处,坐看云起时
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术随笔

    • git教程
    • 前端模块化:CommonJS,AMD,CMD,ES6
    • 如何动态加载本地图片
    • GitHub自动部署脚本
    • React生命周期详解
    • 将父组件的props作为组件的初始state的几种方案
    • webpack基础入门
    • StackOver记录:如何在function中使用redux
    • React中使用onClick时的三种性能优化
    • 思考React状态管理
    • forEach/for..in/of
    • styled-components使用记录
    • 深入理解forEach与forof
    • Node技术架构
    • Redux、Mobx状态管理杂谈
    • JS中的类型检测
    • 如何判断图片是否在可视区域
    • 如何使用图片的懒加载操作
    • JavaScript模块化:从CommonJS到AMD
    • git查看:修改用户名、密码
    • 保持数据Immutable的几种写法
    • 如何实现一个Promise.all
    • resolve(Promise对象)会多出两个微任务
    • todo_基于Mocha的测试驱动开发
    • 浏览器页面渲染机制
    • todo-响应式编程之数据劫持
    • todo-immer库的介绍
    • React-Hooks 基础原理解析
    • JS基本功
    • 函数闭包与this指针
    • 收集 DUMI 配置过程中遇到的问题
    • typescript 类型工具
    • 统一接口的导入导出
    • 网络安全:如何预防 XSS 攻击
    • 浏览器页面渲染机制【2023】
    • 跨域资源请求
      • 0.前言
      • 1. CORS 跨域相关
        • 1. 如何区分简单请求和复杂请求?
        • 2.服务端如何处理简单请求的跨域?
        • 3. 服务端如何处理复杂请求的跨域?
        • 4. 复杂请求响应字段的 Access-Control-Max-Age 的含义?
        • 5. 服务端为什么不推荐 Access-Control-Allow-Origin 设置为星号 ?
        • 6. Cookie 的使用方式
        • 7. CORS 请求中,JS 如何获取 http 的响应头信息?
      • 8. 为啥 Content-Type 支持的类型?
      • 参考资料
    • 浏览器事件循环机制
    • 如何理解浏览器的 user agent 用户代理的含义?
  • 转载文章

  • Mac相关

  • 前端学习周报

  • 包管理工具

  • 技术随笔
  • 技术随笔
wangjiasheng
2023-10-09
目录

跨域资源请求

# 0.前言

这块知识点挺琐碎的,基本都了解,但是总是有些小点总是记不住。

# 1. CORS 跨域相关

# 1. 如何区分简单请求和复杂请求?

只要同时满足以下两大条件,就属于简单请求:

# Method
HEAD
GET
POST

# Headers
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:
   -  application/x-www-form-urlencoded
   -  multipart/form-data
   -  text/plain
1
2
3
4
5
6
7
8
9
10
11
12
13
14

请对如下请求做出判断:

// 简单请求
fetch("http://crossdoman.com/api/news")

// 请求方法错误
fetch("http://crossdoman.com/api/news",{ method: "PUT" })

// 请求头
fetch("http://crossdoman.com/api/news", {headers: {a:1}})

// 典型场景:当 payload 字段为 json 时,也属于跨域
fetch("http://crossdoman.com/api/news", {
  headers: {"content-type":"application/json"},
  method: "post",
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2.服务端如何处理简单请求的跨域?

【浏览器】默认行为:

  • 在头信息之中,增加一个Origin字段

    GET /cors HTTP/1.1
    Origin: http://api.bob.com 【自定添加】
    Host: api.alice.com
    Accept-Language: en-US
    Connection: keep-alive
    User-Agent: Mozilla/5.0...
    
    1
    2
    3
    4
    5
    6

【服务端】行为:

  • 对简单请求的响应

    只需要去判断 Origin 是否是指定源,如果成功。

    Access-Control-Allow-Origin: http://api.bob.com 【通过此属性判断是否成功】
    Access-Control-Allow-Credentials: true
    Access-Control-Expose-Headers: FooBar
    Content-Type: text/html; charset=utf-8
    
    1
    2
    3
    4

    🚨 注:此错误无法通过状态识别,响应状态码很有可能为 200,但可被 XMLHttpRequest的onerror回调函数捕获

# 3. 服务端如何处理复杂请求的跨域?

【浏览器】默认行为:

`OPTIONS` 预检请求 : 同上,默认也会在头信息之中,增加一个`Origin`字段
        ↓
真实 `AJAX` 请求 (XMLHttpRequest)
1
2
3

示例脚本:

var url = 'http://api.alice.com/cors';    // ❎ 跨域
var xhr = new XMLHttpRequest();       
xhr.open('PUT', url, true);               // ❎ 请求方法错误
xhr.setRequestHeader('X-Custom-Header', 'value'); // ❎ 请求头错误
xhr.send();
1
2
3
4
5

【服务端】行为:

  • 对预检请求的响应

    除了 Access-Control-Allow-Origin 字段外,还会校验复杂请求额外要求的请求头(Access-Control-Request-Method) 和方法(Access-Control-Request-Headers)

    跨域请求通过,返回:

    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 01:15:39 GMT
    Server: Apache/2.0.61 (Unix)
    Access-Control-Allow-Origin: http://api.bob.com  【请求源】
    Access-Control-Allow-Methods: GET, POST, PUT     【请求方法】
    Access-Control-Allow-Headers: X-Custom-Header    【请求头】
    Content-Type: text/html; charset=utf-8
    Content-Encoding: gzip
    Content-Length: 0
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Content-Type: text/plain
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    跨域请求不通过,返回

    XMLHttpRequest cannot load http://api.alice.com.
    Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
    
    1
    2

    此错误可被 XMLHttpRequest 对象的 onerror 回调函数捕获。

# 4. 复杂请求响应字段的 Access-Control-Max-Age 的含义?

预检请求后,服务端响应:

Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
1
2
3
4

其中,Access-Control-Max-Age 指定本次预检请求的有效期,单位秒。示例中,1728000 秒(即20天)

在首次 OPTIONS 请求后,以后每次浏览器的 CORS 复杂请求就会和简单请求类似了,示例如下:

预检请求后,浏览器发送:

PUT /cors HTTP/1.1
Origin: http://api.bob.com   【浏览器自动添加】
Host: api.alice.com
X-Custom-Header: value  
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
1
2
3
4
5
6
7

服务端响应:

Access-Control-Allow-Origin: http://api.bob.com  【必须包含】
Content-Type: text/html; charset=utf-8
1
2

# 5. 服务端为什么不推荐 Access-Control-Allow-Origin 设置为星号 ?

与 Cookie 有关,对于 Cookie 来说,依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。

因此,如果需要携带 Cookie 一定要指定明确的、与请求网页一致的域名。

# 6. Cookie 的使用方式

ajax 的跨域请求默认不会附带 cookie ,原生 ajax 需如下配置:

对 xhr 的配置:

// xhr 
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
1
2
3

对于 fetch 的配置

// fetch
fetch(url,{ credentials: true });
1
2

服务端配置:

Access-Control-Allow-Credential: true
Access-Control-Allow-Origin: "明确的域名"
1
2

# 7. CORS 请求中,JS 如何获取 http 的响应头信息?

对于 CORS 请求时,通过 XMLHttpRequest 对象的 getResponseHeaders() 方法,可以获取:

  1. Cache-Control
  2. Content-Language
  3. Content-Type
  4. Expires 和 Last-Modified
  5. Pragma

正常只能访问以上几个响应信息,如果需要访问其余的响应头,需要通过服务端设置

# 浏览器访问的头放入白名单
Access-Control-Expose-Headers: authorization
1
2

JS 代码:

getResponseHeader('authorization')
1

# 8. 为啥 Content-Type 支持的类型?

为啥 Content-Type 支持如下值:

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

原因,兼容表单 form 组件,在 Ajax 技术出现之前,都是使用 form 表单实现的跨域请求。

# 参考资料

  1. 阮一峰:跨域资源共享 CORS 详解 (opens new window)
编辑 (opens new window)
上次更新: 2023/10/21, 0:10:00
浏览器页面渲染机制【2023】
浏览器事件循环机制

← 浏览器页面渲染机制【2023】 浏览器事件循环机制→

最近更新
01
如何理解浏览器的 user agent 用户代理的含义?
11-05
02
浏览器事件循环机制
10-31
03
浏览器页面渲染机制【2023】
10-15
更多文章>
Theme by Vdoing | Copyright © 2020-2023
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式