面试题:什么是跨域?出现的原因?如何解决跨域问题?

2023-10-30

跨域:浏览器不能执行其他网页的脚步,由浏览器的同源策略造成的,是浏览器对javascript实施的安全限制,(无法跨域是浏览器对用户安全的考虑,如果自己写个没有同源策略的浏览器,完全不用考虑跨域问题)同源策略限制 Cookie,localStorage和indexDB(js面向对象的数据库)无法读取,DOM 和JS 对象无法获取,Ajax请求发送不出去

出现的原因:如果使用Ajax异步请求,如果这个请求的URL地址与当前地址栏中的URL地址协议不同,域名不同,端口号不同,都会造成跨域

解决方案:

一,通过jsonp

通常为了减轻web服务器的负载,我们把js css img 等静态资源分离到另一台独立域名的服务器上,在html页面通过相应的标签从不同域名下加载静态资源,而被浏览器允许,

1)原生实现:

服务端返回如下(返回时即执行全局函数):

onBack({"status": true, "user": "admin"})

2)jquery ajax:

 3)vue.js:

 

 后端node.js代码示例:

 jsonp缺点:只能实现get一种请求。

二,document.domain + iframe跨域

此方案仅限主域相同,子域不同的跨域应用场景。

实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

1)父窗口

 2)子窗口

 三,.location.hash + iframe跨域

实现原理:a域与b跨域相互通信,通过中间页C来实现,三个页面,不同域之间通过iframe的location.hash 进行传值,相同域之间直接通过js访问来通信

具体实现:A域:a.html==>B域:b.html==>A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。

1)a.html:

 2)b.html

 3)c.html:

 四, window.name + iframe跨域

window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

 2)proxy.html:

中间代理页,与a.html同域,内容为空即可。

 3)b.html:

 总结:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

五、 postMessage跨域

postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
a) 页面和其打开的新窗口的数据传递
b) 多窗口之间消息传递1)a.html:
c) 页面与嵌套的iframe消息传递
d) 上面三个场景的跨域数据传递

用法:postMessage(data,origin)方法接受两个参数
data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

1)a.html:

 2)b.html:

 

六、 跨域资源共享(CORS)

普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。

需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。如果想实现当前页cookie的写入,可参考下文:七、nginx反向代理中设置proxy_cookie_domain 和 八、NodeJs中间件代理中cookieDomainRewrite参数的设置。

目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。

1、 前端设置:

1)原生ajax:

 2)jQuery ajax:

 3)vue框架
在vue-resource封装的ajax组件中加入以下代码:

Vue.http.options.credentials = true

2、 服务端设置:

若后端设置成功,前端浏览器控制台则不会出现跨域报错信息,反之,说明没设成功。

1)PHP后台:

response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com");  // 若有端口需写全(协议+域名+端口)
response.setHeader("Access-Control-Allow-Credentials", "true");

2)Nodejs后台示例:

ar http = require('http');
var server = http.createServer();
var qs = require('querystring');
 
server.on('request', function(req, res) {
    var postData = '';
 
    // 数据块接收中
    req.addListener('data', function(chunk) {
        postData += chunk;
    });
 
    // 数据接收完毕
    req.addListener('end', function() {
        postData = qs.parse(postData);
 
        // 跨域后台设置
        res.writeHead(200, {
            'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie
            'Access-Control-Allow-Origin': 'http://www.demo1.com',    // 允许访问的域(协议+域名+端口)
            'Set-Cookie': 'l=a123456;Path=/;Domain=www.demo2.com;HttpOnly'   // HttpOnly:脚本无法读取cookie
        });
 
        res.write(JSON.stringify(postData));
        res.end();
    });
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

七、 Nodejs中间件代理跨域

node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。

1)前端代码示例:

 2)中间件服务器:

 3)Nodejs后台:

ar http = require('http');
var server = http.createServer();
var qs = require('querystring');
 
server.on('request', function(req, res) {
    var params = qs.parse(req.url.substring(2));
 
    // 向前台写cookie
    res.writeHead(200, {
        'Set-Cookie': 'l=a123456;Path=/;Domain=www.demo2.com;HttpOnly'   // HttpOnly:脚本无法读取
    });
 
    res.write(JSON.stringify(params));
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

2、 vue框架的跨域(1次跨域)

module.exports = {
    entry: {},
    module: {},
    ...
    devServer: {
        historyApiFallback: true,
        proxy: [{
            context: '/login',
            target: 'http://www.demo2.com:8080',  // 代理跨域目标接口
            changeOrigin: true,
            secure: false,  // 当代理某些https服务报错时用
            cookieDomainRewrite: 'www.demo1.com'  // 可以为false,表示不修改
        }],
        noInfo: true
    }
}

八、 WebSocket协议跨域

WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

1)前端代码:

 2)Nodejs socket后台:

// 启http服务
var server = http.createServer(function(req, res) {
    res.writeHead(200, {
        'Content-type': 'text/html'
    });
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');
 
// 监听socket连接
socket.listen(server).on('connection', function(client) {
    // 接收信息
    client.on('message', function(msg) {
        client.send('hello:' + msg);
        console.log('data from client: ---> ' + msg);
    });
 
    // 断开处理
    client.on('disconnect', function() {
        console.log('Client socket has closed.'); 
    });
});

九、 nginx代理跨域:

浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。

location / {
  add_header Access-Control-Allow-Origin *;
}

2、 nginx反向代理接口跨域

跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。

实现思路:通过nginx配置一个代理服务器(域名与demo1相同,端口不同)做跳板机,反向代理访问demo2接口,并且可以顺便修改cookie中demo信息,方便当前域cookie写入,实现跨域登录。

nginx具体配置:

#proxy服务器
server {
    listen       81;
    server_name  www.demo1.com;
 
    location / {
        proxy_pass   http://www.demo2.com:8080;  #反向代理
        proxy_cookie_demo www.demo2.com www.demo1.com; #修改cookie里域名
        index  index.html index.htm;
 
        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.demo1.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}

1)前端代码示例:

2)Nodejs后台示例: 

var http = require('http');
var server = http.createServer();
var qs = require('querystring');
 
server.on('request', function(req, res) {
    var params = qs.parse(req.url.substring(2));
 
    // 向前台写cookie
    res.writeHead(200, {
        'Set-Cookie': 'l=a123456;Path=/;Domain=www.demo2.com;HttpOnly'   // HttpOnly:脚本无法读取
    });
 
    res.write(JSON.stringify(params));
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试题:什么是跨域?出现的原因?如何解决跨域问题? 的相关文章

  • 如何修复 Nuxt 中导航器/窗口/文档未定义的问题

    我试图确定 Nuxt 应用程序内的 UserAgent 和 Retina 信息 但应用程序抛出错误并显示导航 窗口未定义 我如何在 nuxt 应用程序中获取这些信息 const userAgent navigator userAgent t
  • javascript 使用 onclick 创建按钮

    我正在尝试使用 javascript 创建一个具有 onclick 事件的按钮 该事件调用 head 中定义的函数 该函数接收相对于按钮的 dom 对象作为参数 我该怎么做呢 ex
  • 在javascript中使用“return !0”有什么意义吗?

    如果您转到谷歌结果页面并运行rwt toString 你会看到这个函数的返回调用是 return 0 我想不出任何理由为什么这不会总是如此true 这只是一个简写吗true 还是还有更多事情发生 总是如此 但下载需要 2 个字节 0是 2
  • 未捕获的类型错误:this.props.signinUser 不是一个函数(…)

    src actions index js import axios from axios const ROOT URL http localhost 3090 export function signinUser email passwor
  • HTML5 服务器端事件:EventSource 与包装的 WebSocket

    HTML5 服务器发送事件 SSE API 是否只是 HTML5 WebSocket 之上的受限制的 基于事件的 API 在我看来 一个EventSource只是一个WebSocket that Cannot send data 使用tex
  • 在 asp.net vb 中通过第一个下拉列表值填充第二个下拉列表

    我在使用 asp net vb 时遇到了一些问题 我想做的是有2个下拉框 第一个下拉菜单将有 1 2 3 例如 第二个下拉菜单将有 A 乙 C 默认情况下 但是 如果选择 1 我希望第二个下拉菜单自动选择 c 我不知道 JavaScript
  • 为什么将数据存储为元素的属性存在风险?

    我一直在读同样的东西 直接在 DOM 元素上存储属性值是有风险的 因为可能会发生内存泄漏 但有人可以更详细地解释这些风险吗 按属性 我假设您指的是 DOM 元素上的属性 DOM 元素上的自定义属性安全吗
  • JQuery 动画文本

    找到简单 简单的动画文本是非常困难的 喜欢这个网站上的 内爆 http codecanyon net item jquery text animation full screen preview 233445 http codecanyon
  • 在 Angular2 项目中集成 Treant-js

    我正在尝试在 Angular2 项目中使用 treant js 但我正在努力解决如何正确集成它的问题 我有一个工作正常的 JavaScript HTML 示例 我正在尝试在 Angular2 中工作 我创建了一个组件 从 npm 添加了 t
  • 在 JavaScript 中比较表单中的两个数字

    当我尝试比较不同的数字时 数字发生变化 但文本部分保持不变 这只发生在较大 较小的情况下 而不会发生在 NaN 或相等的情况下 这是我的代码 function check var a document getElementById a va
  • Telegram 授权无默认按钮

    使用 Telegram 第 3 方授权的唯一有记录的方法是使用其提供的脚本https core telegram org widgets login https core telegram org widgets login 这个脚本 正如
  • 光滑的轮播缓动示例

    我正在使用 Slick Carousel http kenwheeler github io slick http kenwheeler github io slick 但不知道如何合并不同的幻灯片切换 有人有例子可以分享吗 这是我目前拥有
  • ReactJS:从没有 onChange 事件的 props 中选择默认值?

    所以 我只是想知道我是否绝对需要在 React 中的选择组件上有一个 onChange 事件处理程序 我有一个道具传递我想要选择的选项的默认值 如果我有的话 它就没有问题
  • Chrome Javascript 调试器暂停时不会重新加载页面

    有时 当我在 Chrome 中调试某些 javascript 并且暂停了 javascript 时 如果我尝试重新加载页面 chrome 只会 继续 调试器 单步执行到下一个断点 似乎没有任何方法可以强制 javascript 完全停止运行
  • setInterval 内的返回值

    我想在 setInterval 内返回一个值 我只想以一定的时间间隔执行一些操作 这就是我尝试过的 function git limit var i 0 var git setInterval function console log i
  • 将 JavaScript 引擎嵌入到 .NET 中 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 只是想知道是否有人尝试过将任何 js 引擎嵌入并实际集成到 net 环境中 我可以找到并实际使用 经过L
  • 使用 JavaScript 的计时器

    我想使用java脚本实现计时器 我想随着间隔的变化而减少计时器 Example假设我的计时器从 500 开始 我想要根据级别减少计时器 例如1 一级定时器应减1 且递减速度应较慢 2 2级定时器应递减2 递减速度应为中等3 3级定时器应减3
  • Meteor.js 登录事件

    因此 我对 Meteor 框架和 JavaScript 总体来说还很陌生 但我正在使用该框架开发一个小项目 以尝试让自己达到标准 基本上我正在开发一个微博客网站 目前 用户可以通过多种服务登录 fb google 等 我通过插入所需 url
  • 使用 React React-router 登录后重定向到主页,并且 usenavigate 不起作用?

    我希望用户在成功登录后重定向到主页 我将用户登录的 api 请求的数据存储在一个名为 currentUser 的变量中 因此如果 currentUser 为 true 它应该重定向到主页 这就是我处理登录请求的方式 export const
  • 如何根据所需表单输入的值更改 CSS 样式

    我想知道如何编写 javascript 来改变所需的表单元素的样式 如果它们有价值的话就改变它们 我想要做的是当所需的文本字段为空时 在它们周围有一个彩色边框 并在它们有值时删除边框样式 我想做的是编写一个 javascript 函数来检查

随机推荐

  • Spring Boot框架基础介绍

    Spring Boot 是一款基于 Spring 框架的开源应用程序开发工具 它旨在简化 Spring 应用程序的配置和开发过程 Spring Boot 提供了一种简单的方式来创建可独立运行的 生产级别的应用程序 并在需要时进行部署 Spr
  • PHP获取网络图片保存到本地

    PHP获取网络图片保存到本地 if fopen dg image r php判断图片是不是网络图片 filename upload goods image g id jpg if file exists filename dg image
  • Win10中使用Hyper-V安装Ubuntu18.04、实现ssh远程连接及Hpyer-V中Ubuntu全屏问题

    利用Windows10自带的虚拟机Hyper V安装Ubuntu18 04 并实现配置主机通过ssh连接Hpyer V中Ubuntu虚拟机 同时解决Ubuntu虚拟机在Hpyer V全屏时不能铺满屏幕的问题 首先安装Hyper V 打开Wi
  • hexo博客优化之文章置顶+置顶标签

    本文首发于wangwlj com 博文置顶 一种方法是手动对相关文件进行修改 具体可参考这篇文章 另一种方法就是 目前已经有修改后支持置顶的仓库 可以直接用以下命令安装 npm uninstall hexo generator index
  • 剑指Offer—— 链表的公共点

    题目表述 输入两个链表 找出它们的第一个公共结点 首先要明白一点 两条链表相交 则他们的形状类似Y 而不是X 所以 从相交的点以后 两条链表的所有结点都是一样的 我们只要找出第一个相同的结点即可 1 我们分别算出两条链表的长度 2 算出两条
  • 用AI配置一台高性能电脑

    首先 并没有什么性价比很高的台式机 这个前提肯定是要有参考物的 比如你要用这个电脑主要是干嘛的 办公的 打游戏的 其次是预算了 我是打游戏的 你给我配一台办公的 办公的肯定性价比高 便宜 但并不符合我实际的需求 例 游戏电脑配置清单 i5
  • Makefile中的匹配符%

    一 匹配符 Make命令允许对文件名 进行类似正则运算的匹配 主要用到的匹配符是 比如 假定当前目录下有 f1 c 和 f2 c 两个源码文件 需要将它们编译为对应的对象文件 o c 等同于下面的写法 f1 o f1 c f2 o f2 c
  • 浏览器查找js绑定或者监听的事件

    1 打开浏览器审核模式 2 选择源代码 3 最右边有个事件监听断点 4 以触摸模式为例 如果代码中有监听触屏事件 移动的时候就会触发相关js代码 并找到位置
  • Linux线程介绍(Linux 系统编程)

    进程与线程 典型的UNIX Linux进程可以看成只有一个控制线程 一个进程在同一时刻只做一件事情 有了多个控制线程后 在程序设计时可以把进程设计成在同一时刻做不止一件事 每个线程各自处理独立的任务 进程是程序执行时的一个实例 是担当分配系
  • 性能测试必备监控技能windows篇

    前言 在手头没有专门的第三方监控时 该怎么监控服务指标呢 本篇就windows下监控进行分享 也是我们在进行性能测试时 必须掌握的 下面我们就windows下常用的三种监视工具进行说明 任务管理器 资源监视器 性能监视器 在 开始 gt 开
  • 分页、关联查询优化

    文章目录 一 分页查询示例 1 分页查询优化 1 1 根据自增且连续的主键排序的分页查询 1 2 根据非主键字段排序的分页查询 二 Join关联查询优化 1 Join关联查询示例表 2 常见表关联算法 2 1 嵌套循环连接 Nested L
  • 跟据经纬度实现附近搜索

    现在很多手机软件都用附近搜索功能 但具体是怎么实现的呢 在网上查了很多资料 mysql空间数据库 矩形算法 geohash我都用过了 当数据上了百万之后mysql空间数据库方法是最强最精确的 查询前100条数据只需5秒左右 接下来推出一个原
  • IIS设置连接超时

    连接超时有助于减少由空闲连接消耗的处理资源损失 启用连接超时时 IIS 会在连接级别执行以下类型的连接超时 客户端已向服务器发送了数据 现处于空闲状态造成的连接超时 已建立了与服务器的连接 但客户端未发送数据时造成的服务器侦听超时 响应超时
  • 使用 Jenkins 实现Android自动化打包和踩坑经历

    每当有项目做的过程中 测试需要做单元测试 每次手动的切换生产和测试环境 切换各种推送 统计和第三方账号相当的麻烦 同时还需要暂存代码 切换分支深的太过繁琐 此时如果将项目配置自动化打包了 那么就可以将这些问题解决了 我们来看一下Jenkin
  • Web渗透测试实战——(1)Web渗透测试简介

    Web渗透测试实战 1 Web渗透测试简介 一 什么是渗透测试 二 渗透测试类型 三 渗透测试阶段 1 信息收集与侦查 2 枚举 3 漏洞评估与分析 4 漏洞利用 5 报告 四 常用的测试方法学 五 推荐的测试平台 一 什么是渗透测试 渗透
  • ubuntu vnc 内网穿透远程连接

    实现ubuntu 系统桌面级别的远程连接 需要在ubuntu 系统中安装vnc 既然是桌面 前提是需要ubuntu 带有图形化界面 如果没有 可以执行以下命令安装图形化界面 sudo apt install ubuntu desktop s
  • 快速熟悉Vue项目

    一 快速梳理大型vue项目整体架构技巧方法总结 首先对于Vue Cli搭建的项目 一定要知道项目的目录结构 如果目录结构都不了解 那一定会很头痛 查看 package json 配置文件 了解项目引用了哪些额外插件和框架 查看 router
  • Keras框架下的猫狗识别(二)

    Tensorflow学习 使用jupyter notebook Keras框架下的猫狗识别 一 模型构建与训练 Tensorflow学习 使用jupyter notebook 前言 一 数据预处理 二 使用步骤 1 引入库 2 定义模型 3
  • 检错纠错码(奇偶校验码 CRC循环冗余校验码 海明码)

    检错与纠错码在计算机中经常被使用 在此对常用的三种检错纠错码做一个介绍 分别是奇偶校验码 CRC循环冗余校验码和海明码 奇偶校验码 通常所说的奇偶校验码指的是一维奇偶校验码 它只能检错 不能纠错 只有二维奇偶校验码具备纠错能力 校验方法 分
  • 面试题:什么是跨域?出现的原因?如何解决跨域问题?

    跨域 浏览器不能执行其他网页的脚步 由浏览器的同源策略造成的 是浏览器对javascript实施的安全限制 无法跨域是浏览器对用户安全的考虑 如果自己写个没有同源策略的浏览器 完全不用考虑跨域问题 同源策略限制 Cookie localSt