✨
blog
  • Blog
  • Element-UI
    • 2019-09-04
  • JS
    • ES6 之 Set 和 Map
    • let 和 const 声明常见概念
    • 元编程
    • ES6之字符串的扩展
    • ES6 之异步流程的前世今生(上)
    • ES6之异步流程的前世今生(下)
    • ES6 之模块你知吗
    • ES6 之解构赋值与箭头函数的妙用
    • 迭代器
    • ES5 之原型(一)
    • ES6之类(二)
    • es7之装饰器
    • es6之数组详解
    • js之this指向
    • 对象
    • vue项目配合使用canvas联动
    • 本文解决痛点:对象里面是否有值
  • MAC
    • vue源码之method
    • Mac的使用技巧
    • 前文
    • Mac常用软件(二)
    • 如何查看 Mac 端口号以及占用情况
  • Node
    • Node之Buffer详解
    • 浏览器与 node 的事件循环(event loop)有何区别
    • Node之多线程
    • node之模块解析(一)
    • 错误捕获与内存告警
  • TS
    • Record
    • 使用方法
    • 工具泛型
    • 类型体操
    • 泛型
  • chrome
    • v8 引擎
    • v8 垃圾回收机制
    • 浏览器的知识
  • flutter
    • 路由
    • 页面布局
  • go
    • index
  • html&css
    • 两栏布局
    • ES5和ES6的区别
    • ES5 和 ES6 的区别
    • HTTP详解
    • TCP 与 UDP 的区别
    • MDN
    • css modules 使用教程
    • css 居中
    • 拖拽
    • flex布局
    • h5 新增特性 html5
    • history 与 hash 路由策略
    • position 定位方式
    • rem布局
    • svg
    • web性能优化
    • 事件循环
    • 从输入网址后发生了什么
    • 前端状态管理
    • 圣杯布局与双飞翼
    • 性能优化 页面的性能统计指标
    • 本地存储的几种对比
    • 浏览器的渲染进程
    • 浏览器缓存策略详解
    • 盒模型
    • 为什么要移动端适配
    • 跨域的 N 种实现方式
  • web3
    • 常见概念
    • vue项目配合使用canvas联动
  • webgl
    • Mac使用技巧(二)
    • Node之模块解析path
  • 代码库
    • documeng的一些常见操作
    • eventBus事件
    • jquery提交
    • jquery的一些常见操作
    • 常见操作
    • 数组polyfill
    • TS代码片段
      • 面试官眼中的test unit
  • 全年安排
    • AfterShip
    • 大企业
  • 函数编程题
    • Promise问题
    • 继承
  • 前端早早聊
    • vue生态
    • 开发一款VScode语言插件
    • 简历回顾和进行复盘
    • 重新认知性能优化及其度量方法
    • 2022-09-17-音视频专场.md
      • 2022-09-17-音视频专场
    • 前端晋升专场
      • 成长的诀窍是靠自己
      • 销销帮
    • 前端监控专场
      • 字节前端监控实践
      • 李港:大前端-从无到有搭建自研前端监控系统
    • 前端跳槽
      • 50个面试官在线招聘
      • 如何识别优秀的前端猎头来跳槽大厂
      • 面试套路
    • 支付宝
      • 面试
    • 管理专场
      • 芋头:管理者眼中的web技术发展前沿
    • 组件专场
      • 基于webCompents的跨技术组件库实践
    • 面试
      • 面试辅导问题
      • 早早聊面试
      • 前端沙箱是什么? 怎么实现沙箱环境?
  • 常见总结
    • 2018年终总结-年底了,你总结了吗?我先来
    • 在逆境中成长
    • 2021年终总结
    • 2024年全年总结
    • 项目
    • Tell2.0 前端复盘
    • 复盘
    • 前端工程师素养
    • 学习方法论
    • 希望与破晓| 2022 年终总结
    • 新起点, 新征途 | 掘金年度征文
    • 稳定| 2023 年终总结
    • 趁着有风快飞翔 | 2019 年终总结
    • AfterShip
      • Emotion:用 JavaScript 编写 CSS 的强大工具
      • 个人中长期目标
      • 事故复盘
      • 时间解析
      • 国内外区别
      • 独立站建设
    • MEIZU
      • NativeApp与H5通信原理
      • SSR 原理
      • SSR的常见问题
      • CLI
      • electron 应用发布流程
      • electron
      • electron 面试
      • 数据结构与算法之美
      • mgc 一期复盘
      • 架构原理
      • 喵币管理
      • 三期复盘总结
      • 异常监控之 sentry 实践
      • 微前端
      • qiankun 原理解析
      • 快游戏一期
      • 游戏中心复盘
    • 个人准则
      • index
    • 编程猫
      • pc 接入 micro bit 方案
      • prompt engineer
      • web work 跨域解析与解决方式
      • web 中的 ai
      • 低版本 node 环境下 ffmpeg 的使用
      • 关于 taobao 源 https 过期
      • 加密 json
      • 安卓 5 和 6 的白屏解决
      • 性能排查与优化实践
      • 探月接入
      • 接入硬件
      • 新生态下的state
      • monorepo 包管理方式
      • 自修复 npm 库
      • 音频的绘制
    • 谨启
      • 音视频
      • 小程序
        • taro 规范
        • 结合 mobx 在跳转前预请求
        • Taro 浅析用法与原理
        • 前文
        • 小程序优化指南
        • 小程序内部实现原理
        • 支付相关
    • tencent
      • TAPD
        • MathJax的食用
        • canvas渲染优化策略
        • 为什么 JavaScript 是单线程的呢?
        • svg 总是不对
        • 前端库
        • 原生端和js端如何通信
        • 在旧项目中复用vue代码
        • 提升自我
        • 批量编辑优化
        • 插入业务对象
        • 编辑器
        • 挂载点
        • 性能优化对比
        • 遇到的问题
        • 项目迁移公告
        • 领导力
      • 行家
        • 实战篇
        • 职业发展、领导力、个人成长
        • 高质量沟通
  • 慕课网
    • react-native原理
    • react-native学习
  • 杂文
    • Dom 节点变动检测并录制的简单实现
    • 错误监控&错误捕获
    • NextJS与NuxtJS
    • 负载均衡的几种常用方式
    • PM2
    • service worker 控制网络请求?
    • SSL 和 TLS 的区别
    • Babel 你太美
    • echart踩坑经验
    • keyup、keydown你都知道有什么区别吗
    • 常见概念
    • 首屏加载优化与性能指标分析
    • preload 和 prefetch 的详解
    • 在项目中配置这几个关系
    • roullp 解析
    • tinymce原理浅析
    • wasm 在前端的应用
    • websocket
    • webworker
    • 项目
    • 从 ajax 到 axios
    • 从postcss 到自己开发一款插件
    • 从输入浏览器到页面展示涉及的缓存机制
    • 代码整洁之道
    • 你知道什么是aop吗
    • 函数式编程
    • 函数式编程指南
    • 前端input框文字最大值
    • 攻坚战
    • 前端书写 sdk
    • 前端文字转语音播放
    • 前端领域的 Docker 和 Kubernetes
    • 前端安全
    • 前端进阶之内存空间
    • 前端音频浅析
    • 十分钟搞定多人协作开发
    • 字符串的比较
    • 尾递归
    • 前文
    • 常见的算法可以分为以下三类
    • 手机调试--mac篇
    • 数组的原生系列
    • COOP 和 COEP - 新的跨域策略
    • 浅谈react组件书写
    • 浏览器与 Node.js 事件循环的区别
    • 由三道题引伸出来的思考
    • 移动端300ms点击延迟
    • 移动端和pc端事件
    • Git 常见疑惑
    • 我们离发 npm 包还有多远
    • 重绘和重排
    • AI 时代下的前端编程范式
    • 音频可视化实战
  • 极客时间
    • Serverless入门课
    • 二分查找
    • 二叉树
    • 全栈工程师
    • 动态规划面试宝典
    • 前端与rust
    • 散列表
    • 前端方面的Docker和Kubernetes
    • 栈
    • 深入浅出区块链
    • 玩转 vue 全家桶
    • 玩转 webpack
    • 程序员的个人财富课
    • 算法
    • 说透元宇宙
    • 跳表
    • 链表
    • 10x 程序员工作法
      • index
    • Node开发实战
      • HTTP服务的性能测试
      • JavaScript语言精髓与编程实战
      • 什么是node。js
      • svg精髓
    • ReactHooks核心原理与实战
      • ReactHooks核心原理与实战
    • Rust
      • Rust编程第一课
      • 前置篇
      • 深度思维
      • 重构
      • 类型体操
      • 基础知识
    • WebAssembly入门课.md
      • 基础篇
      • SSR的注水和脱水
      • jsBriage通信原理
      • 基础知识篇
    • 互联网的英语私教课
      • 互联网人的英语私教课
    • 代码之丑
      • 代码之丑
    • 前端全链路优化实战课
      • 网页指标
    • 图解 Google V8
      • 图解 Google V8
    • 浏览器工作原理与实践
      • 浏览器工作原理与实践
    • 算法面试通关 40 讲
      • 算法面试通关40讲
    • 跟月影学可视化
      • index
    • 软件设计之美
      • 软件设计之美
    • 重学前端
      • js
  • 后续的文件增加都会增加到上面并以编号对应
    • 1029. 两地调度
    • 151.翻转字符串里的单词
    • 2022.3.15
    • 前端数据结构
    • 前端常见算法
    • 前端常见排序
    • 恢复一棵树
  • 设计模式
    • 前端常见设计模式之MVC与MVVM
    • 前端之代理模式
    • 前端常见设计模式之单例模式
    • 前端常见设计模式之发布订阅模式
    • 前端之工厂模式
    • 观察者模式
    • 前端常见设计模式之适配器模式
  • 译文
    • [译] 如何使用CircleCI for GitHub Pages持续部署
    • 您是否优化了 API 的性能
    • [译][官方] Google 正式发布 Flutter 1.2 版本
    • 什么是 Deno ,它将取代 NodeJS ?
  • 读后感
    • JavaScript二十年
    • 1368个单词就够了
    • js编程精解
    • labuladong 的算法小抄
    • lodash常用方法
    • vue的设计与实现
    • 所有的静态资源都是get请求
    • 人生
    • 人生护城河
    • 你不知道的JavaScript
    • 前端核心知识进阶
    • 华为工作法
    • 反脆弱
    • 好好学习
    • 左耳听风
    • 摩托车维修之道
    • 数学之美
    • 深入理解svg
    • 浏览器的ESM到底是啥
    • 经济学原理
    • 编程珠玑
    • 防御式 css 精讲
    • 韭菜的自我修养
  • 雪狼
    • 2022-07-17
    • 基础知识
    • 阶一课程
      • 实战辅导一
      • 实战辅导二
  • 嵌入式
    • 树莓派
      • 排序
  • 源码
    • React
      • 核心知识点
      • errorBoundaries
      • immutable.js 的实现原理
      • React.Suspense
      • react源码分析之Fiber
      • batchedUpdate
      • Component
      • Context
      • react 源码分析之 diff 算法
      • React 中的 key 属性:原理、使用场景与注意事项
      • 使用方式
      • react源码分析之memo
      • react 源码分析之mixin
      • 实战篇
      • react源码分析之react-dom
      • 使用方式
      • scheduleWork
      • useImperativeHandle的使用与原理
      • React 书写小技巧
      • 入口和优化
      • 合成事件和原生事件的区别
      • react 性能优化
      • 构建一个 hooks
      • 浅析 styled-components
      • 生命周期
      • 组合 vs 继承
      • 通信机制
      • 高阶组件
      • 慕课网
        • 应用篇
        • 课程导学
    • ReactHook
      • useCallback
      • useContext
      • useEffect 与 useLayoutEffect
      • useHook
      • useMemo
      • useReducer
      • 原理
      • useState
      • 总结
    • Redux
      • mobx 原理解析
      • redux-saga
      • redux-thunk
      • Mobx 和 Redux 对比
      • 使用方法
      • redux 原理
    • Vite
      • Vite原理
      • Vite配置
      • 热更新原理
      • vite 为什么生产环境用 Rollup
    • Webpack
      • PostCSS
      • Webpack5 核心原理与应用实践-loader
      • Webpack5 核心原理与应用实践-plugin
      • Webpack5 核心原理与应用实践
      • 区分
      • 升级详情
      • treeShaking(树摇Tree Shaking)
      • 编写一个自己的webpack插件plugin
      • 代码分离(code-splitting)
      • webpack 打包优化
      • 基础配置
      • webpack 打包优化
      • webpack 工作原理
      • webpack 按需加载原理
      • webpack 热更新 HMR(Hot Module Replacement)
      • 缓存
      • webpack 自定义 plugin
    • next
      • tailwind
      • 什么是水合
    • sveltejs
      • index
    • tinymce
      • 并发篇
    • 源码手写系列
      • create
      • call
      • bind
      • call
      • es6 单例
      • forEach vs Map
      • instanceOf
      • new
      • reduce
      • 取两个重复数组的交集
      • 函数柯理化
      • 动态规划
      • 基于Generator函数实现async
      • 新建 js 文件
      • 手写一个 slice 方法
      • 手写一个 webpack loader
      • Plugin
      • 手写一个寄生组合式继承
      • 二叉树
      • 链表相关的操作
      • 手动实现发布订阅
      • 数组去重
      • 数组扁平化
      • 数组
      • 构造大顶堆和小顶堆
      • 深浅拷贝 深拷贝
      • 两者对比
    • vue
      • vue2
        • vm.attrs与$listeners
        • vue 和 react 的 diff 算法比较
        • vue 源码分析
        • vue 优化的 diff 策略
        • extends
        • 核心原理篇
        • keep-alive
        • vue 源码分析之 mixins
        • vue 源码分析之 nextTick
        • vue之slot
        • vnode
        • vue 源码分析之 watch
        • 原理
        • vue 源码分析之transition
        • vue 源码分析之异步组件
        • 调用的是 watch
        • 安装
        • react源码分析之portals
        • event 的实现原理(事件的实现原理)
        • 什么是h
        • 分析provide 和 inject
        • vue 源码分析之 use
        • v-model
        • vue源码分析之vuex
        • 响应式原理
        • 初始化的流程
        • 组件更新
        • 编译
        • 父子组件生命周期
        • 原理
        • 多实例
        • Vue 面试
        • 源码研读一
        • 响应式原理
        • 常见问题
        • 数组的劫持
        • vue之自定义指令
        • 运行机制全局概览
      • vue3相比vue2的提升点
        • vue composition api
        • vue3的虚拟dom优化
        • vue3层面的双向数据绑定
        • 预处理优化
  • 重构
    • notification
      • 讲解
  • 面试
    • AfterShip经历
      • JS对URL进行编码和解码
      • ShippingLabelTemplate
      • 接入keycloak详解
      • reCAPTCHA接入
      • yalc与动态解决升级的依赖包
      • RBAC 简介
      • 多语言计划
      • 接入Google登录及其主动弹出快捷登录方式
      • 读书计划
        • 传染
        • 这就是OKR
    • 编程猫经历
      • 2024.1.16
      • 2025.2.20
      • 2025.2.21
      • 2025.2.26
      • 2025.3.28
      • 2025.3.3
      • 2025.3.7
      • 行动轨迹
      • 面试主观题
    • 腾讯经历
      • 2022.02.21
      • 2022.03.30
      • 2022.04.24
      • 2022.04.25
      • 2022.04.27
      • 2022.04.28
      • 2022.04.29
      • 2022.05.05
      • 不同公司的面试关注点不同
      • 2022.05.07
      • 2022.05.09
      • 2022.05.10
      • 2022.05.11
      • 2022.05.12
      • 2022.05.13
      • 2022.05.16
      • 2022.05.17
      • 2022.05.19
      • 2022.05.27
      • 面试
      • 行动轨迹
      • 面试主观题
    • 针对字节
      • 2022.05.14
      • 2022.05.17
      • HR面试准备
      • Promise的相关题目
      • React 进阶实践指南(二)
      • React 面试准备
      • vue 与 react 有什么不同 (react 和 vue 有什么区别)
      • TypeScript 全面进阶指南
      • cookie和session区别
      • express 面试准备 koa 中间件原理
      • next面试准备
      • requestCallBack
      • interface 与 type 异同点
      • 取消 promise
      • 如何设计一个前端项目
      • 进阶篇
      • 早早聊面试准备
      • 自动化部署
      • 挖掘项目的深度
      • 面试
      • 出题指数
    • 魅族经历
      • 2020.09.11
      • 一灯
      • 一灯
      • 一灯
      • 2020.09.20
      • 2020.09.21
      • 网易二面
      • 2020.09.23
      • 头条
      • 360 金融面试题
      • 富途一面
      • 算法
      • 字节
      • 2020.11.04
      • baidu 一面
      • meta 标签的作用
      • 字节
      • 2020.11.22
      • 2020.11.25
      • 微前端接入笔记
      • 面试的基本原则
由 GitBook 提供支持
在本页
  • 跨域的 N 种实现方式
  • 什么是跨域
  • 跨域有什么好处
  • 同源策略限制以下几种行为
  • 怎么实现跨域访问

这有帮助吗?

  1. html&css

跨域的 N 种实现方式

上一页为什么要移动端适配下一页web3

最后更新于2个月前

这有帮助吗?

同源策略引起的跨域问题

同源策略是浏览器的行为,是为了保护本地数据不被 JavaScript 代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。需要注意的是,很多人以为同源策略是浏览器不让请求发出去、或者后端拒绝返回数据。实际情况是,请求正常发出,后端接口正常响应,只不过数据到了浏览器后被丢弃了。

响应策略

同源跨域通信

  1. JSONP

  2. CORS

  3. postMessage

  4. WebSocket

  5. nginx 反向代理

CORS 是为了解决 AJAX 跨域的问题

整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。 CORS 背后的基本思想就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

服务器端对于 CORS 的支持,主要就是通过设置 Access-Control-Allow-Origin 来进行的。如果浏览器检测到相应的设置,就可以允许 Ajax 进行跨域的访问。

比如一个简单的使用 GET 或者 POST 发送的请求,它没有自定义头部,而主体内容是 text/plain。在发送该请求时,需要给它附加一个额外的 Origin 头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。下面是 Origin 头部的一个示例。

JSONP 是通过动态元素来使用的,使用时可以为 src 属性指定一个跨域 URL。 这里的<scriot>元素与<img>元素类似,都有能力不受限制的从其他域加载资源。因为 JSONP 是有效的 JS 代码,所以在请求完成后,即在 JSONP 响应加载到页面中以后,就会立即执行。来看一个例子。

CORS 和 JSONP 对比

JSONP 只能实现 GET 请求,而 CORS 支持所有类型的 HTTP 请求。 使用 CORS,开发者可以使用普通的 XMLHttpRequest 发起请求和获得数据,比起 JSONP 有更好的错误处理。 JSONP 主要被老的浏览器支持,它们往往不支持 CORS,而绝大多数现代浏览器都已经支持了 CORS

跨域的 N 种实现方式

解决跨域的几种方案

跨域, 什么是跨域?跨域有什么好处?跨域有什么不好?怎么实现跨域?

什么是跨域

只要协议、域名、端口有任何一个不同,都被当作是不同的域,之间的请求就是跨域操作. 对于端口和协议的不同,只能通过后台来解决。

跨域有什么好处

防止 CSRF 攻击、同源策略:隔离潜在恶意文件的重要安全机制

或者使用 CSP 建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。 两种方式开启 CSP。

  1. 设置 HTTP Header 中的 Content-Security-Policy

  2. 设置 meta 标签的方式 meta http-equiv="Content-Security-Policy"

Content-Security-Policy: default-src 'self'

Content-Security-Policy: img-src https://*

Content-Security-Policy: child-src 'none'

同源策略限制以下几种行为

同源策略限制内容有:

  • Cookie、LocalStorage、IndexedDB 等存储性内容

  • DOM 节点

  • AJAX 跨域请求的数据

怎么实现跨域访问

  1. JSONP

JSONP 跨域 GET 请求是一个常用的解决方案,下面我们来看一下 JSONP 跨域是如何实现的,并且探讨下 JSONP 跨域的原理

利用在页面中创建

节点的方法向不同域提交 HTTP 请求的方法称为 JSONP,这项技术可以解决跨域提交 Ajax 请求的问题。JSONP 的工作原理如下所述

代码如下:

//server.js
const url = require('url');

require('http').createServer((req, res) => {
    // console.log('req: ', req);
    const data = {
        x: 10
    };
    console.log('url.parse(req.url, true).query: ', url.parse(req.url, true).query);
    const callback = url.parse(req.url, true).query.callback;
    res.writeHead(200);
    res.end(`${callback}(${JSON.stringify(data)})`); // jsonpCallback(data)
}).listen(3000, '127.0.0.1');

console.log('启动服务,监听 127.0.0.1:3000');

//html

function jsonpCallback(data) {
    alert('获得 X 数据:' + data.x);
}
script src = "http://127.0.0.1:3000?callback=jsonpCallback" > < /script>

JSONP 的优点是:它不像 XMLHttpRequest 对象实现的 Ajax 请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要 XMLHttpRequest 或 ActiveX 的支持;并且在请求完毕后可以通过调用 callback 的方式回传结果。

JSONP 的缺点则是:它只支持 GET 请求而不支持 POST 等其它类型的 HTTP 请求;它只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题。

再来一个例子:

//server.js
const url = require("url");

require("http")
  .createServer((req, res) => {
    const data = {
      x: "10",
    };
    console.log(
      "url.parse(req.url, true).query: ",
      url.parse(req.url, true).query
    );
    if (url.parse(req.url, true).query.word === "sjh") {
      const callback = url.parse(req.url, true).query.callback;
      res.writeHead(200);
      res.end(`${callback}(${JSON.stringify(data)})`);
    }
  })
  .listen(3000, "127.0.0.1");

console.log("启动服务,监听 127.0.0.1:3000");

//html
var qsData = {
  word: "shj",
};
$.ajax({
  async: false,
  url: "http://127.0.0.1:3000", //跨域的dns
  type: "GET",
  dataType: "jsonp",
  jsonp: "callback",
  data: qsData,
  timeout: 5000,
  success: function (json) {
    console.log("json: ", json);
    alert(json.x);
    let obj = JSON.parse(json);
    console.log("obj: ", obj);
  },
  error: function (xhr) {
    console.log("xhr: ", xhr);
    //请求出错处理
    alert("请求出错)", xhr);
  },
});

这种方式其实是上例$.ajax({..}) api的一种高级封装,有些$.ajax api 底层的参数就被封装而不可见了。

jquery $.ajax方法名有误导人之嫌。 如果设为dataType: 'jsonp',这个$.ajax 方法就和 ajax

XmlHttpRequest 没什么关系了,这种跨域方式其实与 ajax XmlHttpRequest 协议无关了。 取而代之的则是 JSONP 协议。JSONP 是一个非官方的协议,它允许在服务器端集成 Script tags 返回至客户端,通过 javascript callback 的形式实现跨域访问。

Jsonp 的执行过程如下: 首先在客户端注册一个 callback (如:'jsoncallback'), 然后把 callback 的名字(如:jsonp1236827957501)传给服务器。注意:服务端得到 callback 的数值后,要用 jsonp1236827957501(......)把将要输出的 json 内容包括起来,此时,服务器生成 json 数据才能被客户端正确接收。

然后以 javascript 语法的方式,生成一个 function, function 名字就是传递上来的参数 'jsoncallback'的值 jsonp1236827957501 . 最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。

客户端浏览器,解析 script 标签,并执行返回的 javascript 文档,此时 javascript 文档数据,作为参数, 传入到了客户端预先定义好的 callback 函数(如上例中 jquery $.ajax()方法封装的的 success: function (json))里。

可以说 jsonp 的方式原理上和</>是一致的(qq 空间就是大量采用这种方式来实现跨域数据交换的)。JSONP 是一种脚本注入(Script Injection)行为,所以有一定的安全隐患。

那 jquery 为什么不支持 post 方式跨域呢?

  1. 跨域资源共享 CORS 什么是 CORS

    CORS(cross-Origin Resource Sharing) 跨域资源共享,管理跨源请求。而跨域资源共享是有益的。今天的我们创建的大多数网站加载资源从网络的各个不同的地方, 当我们发送 GET 请求时,大多数情况浏览器头会 Access-Control-Allow-Origin: * 。意思是能够共享资源在任何域名下。否则就是只能在特定的情况下了。 当请求时以下时,将在原始请求前先进行标准预请求,使用 OPTIONS 头,

    http: //www.example.com/foo-bar.html

浏览器访问外部资源时会出现下面这种情况

而我们想要的效果是这种情况.

我们可以在 HTTP 请求头加上 CORS 标准。

  • Access-Control-Allow-Origin

  • Access-Control-Allow-Credentials

  • Access-Control-Allow-Headers

  • Access-Control-Allow-Methods

  • Access-Control-Expose-Headers

  • Access-Control-Max-Age

  • Access-Control-Request-Headers

  • Access-Control-Request-Method

  • Origin

    当我们发送 GET 请求时,大多数情况浏览器头会 Access-Control-Allow-Origin: * 。意思是能够共享资源在任何域名下。否则就是只能在特定的情况下了。

    app.use(cors()); 当请求时以下时,将在原始请求前先进行标准预请求,使用 OPTIONS 头,

  • PUT

  • DELETE

  • CONNECT

  • OPTIONS

  • TRACE

  • PATCH 当我们发的预处理请求并指示原始请求是否安全,如果指定原始请求时安全的,则它将允许原始请求。否则拒接。

options:与 head 类似,是客户端用于查看服务器的性能 。JavaScript 的 XMLHttpRequest 对象进行 CORS 跨域资源共享时,就是使用 OPTIONS 方法发送嗅探请求,以判断是否有对指定资源的访问权限

//npm install cors

response.setHeader("Content-Type", "text/html");

var express = require("express");
var cors = require("cors");

//或者直接设置
res.writeHead(200, {
  "Access-Control-Allow-Origin": "http://localhost:8080",
});
var app = express();

app.use(cors());

app.get("/hello/:id", function (req, res, next) {
  res.json({
    msg: "CORS-enabled!",
  });
});

app.listen(80, function () {
  console.log("CORS-enabled web ");
});
  1. Server Proxy: 服务器代理,当你需要有跨域请求额操作时发送给后端,让后端帮你带为请求,然后将最后的获取的结果发送给你。

//html
$.get("http://127.0.0.1:3000/topics", function (data) {
  consoel.log(data);
});

//server.js
const url = require("url");

const http = require("http");

const server = http
  .createServer((req, res) => {
    const path = url.parse(req.url).path.slice(1);
    console.log("path: ", path);

    if (path === "topics") {
      http.get("http://cnodejs.org/api/v1/topics", (resp) => {
        const { statusCode } = resp;
        const contentType = resp.headers["content-type"];
        console.log("resp: ", statusCode, contentType);
        let error;
        if (statusCode !== 200) {
          error = new Error("Request Failed.\n" + `Status Code: ${statusCode}`);
        } else if (!/^application\/json/.test(contentType)) {
          error = new Error(
            "Invalid content-type.\n" +
              `Expected application/json but received ${contentType}`
          );
        }
        if (error) {
          console.error(error.message);
          // Consume response data to free up memory
          resp.resume();
          return;
        }

        res.setEncoding("utf8");
        let data = "";
        resp.on("data", (chunk) => {
          data += chunk;
        });
        res.on("end", () => {
          try {
            const parsedData = JSON.parse(rawData);
            console.log(parsedData);
          } catch (e) {
            console.error(e.message);
          }
        });
      });
    }
  })
  .listen(3000, "127.0.0.1");

console.log("启动服务,监听 127.0.0.1:3000");
  1. document.domain + iframe

基于 iframe 实现的跨域要求两个域具有 aa.xx.com, bb.xx.com 这种特点,也就是两个页面必须属于一个基础域(例如都是 xxx.com,或是 xxx.com.cn),使用同一协议(例如都是 http)和同一端口(例如都是 80),这样在两个页面中同时添加 document.domain,就可以实现父页面调用子页面的函数,当然这种方法只能解决主域相同而二级域名不同的情况。 代码如下:

//页面一在head内添加js如下:
document.domain = “xx.com”;

function aa() {
    alert(“p”);
}
//body添加iframe和js如下
<
iframe src = ”http: //localhost:8080/2.html“ id=”i”>
    document.getElementById(‘i’).onload = function() {
        var d = document.getElementById('i').contentWindow;
        d.a();
    };
//页面二 head添加如下
document.domain = “xx.com”;

function a() {
    alert("c");
}
//这时候父页面就可以调用子页面的a函数,实现js跨域访问

6.1、通过 location.hash 跨域

以下三种都是通过 iframe 方式来,我们根据 iframe 能够在浏览器下能够跨域的特点,进行通信。

//locationNameA
<
script >

    function startRequest() {
        var ifr = document.createElement('iframe');
        ifr.style.display = 'none';
        ifr.src = 'http://127.0.0.1:5501/locationNameB.html#name';
        document.body.appendChild(ifr);
    }

function checkHash() {
    try {
        var data = location.hash ? location.hash.substring(1) : '';
        if (console.log) {
            console.log('Now the data is ' + data);
        }
    } catch (e) {};
}

setInterval(checkHash, 2000);

</script>
//locationNameB
<script >

    function callBack() {
        try {
            parent.location.hash = 'somedata';
        } catch (e) {
            // ie、chrome的安全机制无法修改parent.location.hash,
            // 所以要利用一个中间的cnblogs域下的代理iframe
            var ifrproxy = document.createElement('iframe');
            ifrproxy.style.display = 'none';
            ifrproxy.src = 'http://127.0.0.1:5502/locationNameC.html#sjh';
            document.body.appendChild(ifrproxy);
        }
    }

    //locationNameC
    <
    script >
    parent.parent.location.hash = self.location.hash.substring(1);
console.log('parent.parent.location.hash: ', parent); <
/script>

6.2 通过 window.name 跨域 window 对象有个 name 属性,该属性有个特征:即在一个窗口(window)的生命周期内, 窗口载入的所有的页面都是共享一个 window.name 的,每个页面对 window.name 都有读写的权限,window.name 是持久存在一个窗口载入过的所有页面中的。window.name 属性的 name 值在不同的页面(甚至不同域名)加载后依旧存在(如果没修改则值不会变化),并且可以支持非常长的 name 值(2MB)。

 window.name = data; //父窗口先打开一个子窗口,载入一个不同源的网页,该网页将信息写入。
 window.location = 'http://a.com/index.html'; //接着,子窗口跳回一个与主窗口同域的网址。
 var data = document.getElementById('myFrame').contentWindow.name。 //然后,主窗口就可以读取子窗口的window.name了。

如果是与 iframe 通信的场景就需要把 iframe 的 src 设置成当前域的一个页面地址。

//http://127.0.0.1:5502/window.nameA.html
let data = '';
const ifr = document.createElement('iframe');
ifr.src = "http://127.0.0.1:5501/window.nameB.html";
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function() {
        ifr.onload = function() {
            console.log('ifr。contentWindow: ', ifr.contentWindow, ifr.contentWindow.name);
            data = ifr.contentWindow.name;
            console.log('收到数据:', data);
        }
        ifr.src = "http://127.0.0.1:5502/window.nameC.html";
    } < /script、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、>

    //http://127.0.0.1:5501/window.nameB.html
    <
    script >
    window.name = "你想要的数据!"; < /script>

//http://127.0.0.1:5502/window.nameC.html

6.3 windows.postMessage

otherWindow.postMessage(message, targetOrigin, [transfer]);

接收数据:data、type:类型、source:对象、origin:源;

//postMessageChild.html
<
iframe src = "./postMessageChild.html"
id = "myFrame" > < /iframe>  <
script >

    iframe = document.getElementById('myFrame')

iframe.onload = function() {

    iframe.contentWindow.postMessage('MessageFromIndex1', '*')

    setTimeout(() => {
        iframe.contentWindow.postMessage('MessageFromIndex2', '*')
    })

}

function receiveMessageFromIframePage(event) {
    console.log('receiveMessageFromIframePage', event)
}

window.addEventListener('messae', receiveMessageFromIframePage, false)

//  postMessageParent.html
parent.postMessage({
    msg: 'MessageFromIframePage'
}, "*");

function receiveMessageFromParent(event) {
    consle.log('receiveMessageFromParent', event)
}

window.addEventListener('message', receiveMessageFromParent, false)
  1. websocket

WebSocket 是一种通信协议,使用 ws://(非加密)和 wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

//html
<
ul > < /ul> <
input type = "text" >
    $(function() {
        var iosocket = io.connect('http://localhost:3000/');
        var $ul = $("ul");
        var $input = $("input");
        iosocket.on('connect', function() { //接通处理
            $ul.append($('<li>连上啦</li>'));
            iosocket.on('message', function(message) { //收到信息处理
                $ul.append($('<li></li>').text(message));
            });
            iosocket.on('disconnect', function() { //断开处理
                $ul.append('<li>Disconnected</li>');
            });
        });

        $input.keypress(function(event) {
            if (event.which == 13) { //回车
                event.preventDefault();
                console.log("send : " + $input.val());
                iosocket.send($input.val());
                $input.val('');
            }
        });
    });

//server.js
var io = require('socket.io')(3000);
io.sockets.on('connection', function(client) {
    client.on('message', function(msg) { //监听到信息处理
        console.log('Message Received: ', msg);
        client.send('服务器收到了信息:' + msg);
    });
    client.on("disconnect", function() { //断开处理
        console.log("client has disconnected");
    });
});
console.log("listen 3000...");
  1. canvas 操作图片的跨域问题

Origin: 如果服务器认为这个请求可以接受,就在 Access-Control-Allow-Origin 头部中回发相同的源信息(如果是公共资源,可以回发'*')。例如:

Access-Control-Allow-Origin: 如果没有这个头部,或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器会处理请求。注意,请求进而响应都不包含 cookie 信息。

假设在

这个页面中向 提交 GET 请求,我们可以将下面的 JavaScript 代码

放在 这个页面中来实现:

当 GET 请求从 返回时,可以返回一段 JavaScript 代码,这段代码会自动执行,可以用来负责调用 页面中的一个 callback 函数

same-origin
cors-origin
OPTIONS

在 url 中, 的 "#la" 就是 location.hash,改变 hash 值不会导致页面刷新,所以可以利用 hash 值来进行数据的传递,当然数据量是有限的。

http://www.nczonline.net
http://www.nczonline.net
http://example1.com/index.php
http://example2.com/getinfo.php
http://example1.com/index.php
http://xx1.html
http://xxx2.html
http://www.a.com#la