js跨域相关面试题

目录

一、什么是跨域

二、同源策略会造成以下的影响

三、跨域解决方案

四、跨域方法详解

1、处理跨域方法一 JSONP

2. 处理跨域方法二 CORS

3、处理跨域方法三——WebSocket

4、处理跨域方法四——postMessage

5、处理跨域方法五vue-cli代理转发


一、什么是跨域

广义的跨域包括:

  • 资源跳转:超链接跳转、重定向、表单提交
  • 资源嵌入:link、ifram、script、img,以及css样式中的background:url()、@font-face()等外链接
  • 脚本请求:js的ajax请求、js或DOM 中的跨域操作

狭义的跨域:指浏览器同源策略限制的请求

同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。


        当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。

在这里插入图片描述

有一点必须要注意:跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。

二、同源策略会造成以下的影响

  • Cookie、LocalStorage 和 IndexDB 无法读取

  • DOM 和 JS 对象无法获取

  • Ajax请求发送不出去

三、跨域解决方案


跨域的方法很多,网上案例很多 常见的大概有9种,分别是

  1. jsonp跨域
  2. document.domain + iframe
  3. window.name + iframe
  4. location.hash + ifram
  5. 跨域资源共享(CORS)
  6. WebSocket协议跨域
  7. HTML5的postMessage跨域
  8. nginx代理跨域
  9. nodejs中间件代理跨域

或者也可以这么分类

对最主要的AJAX跨域来说(也就是平常调接口时):

1)(后端)服务器配置CORS(跨域资源共享)

2)(后端)node.js或nginx,反向代理,把跨域改造成同域

3)(前端)将JSON升级成JSONP,在JSON的基础上,利用<script>标签可以跨域的特性,加上头设置

4)对iframe跨域来说:H5提供了postMessage()的方法,可以在父子页面进行通信(加分项)

在日常工作中,原生js我们使用最多的还是jsonpCORS两种

四、跨域方法详解

1、处理跨域方法一 JSONP

1.JSONP原理

核心思想:浏览器的script、img、iframe标签是不受同源策略限制的 ,所以通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的callback函数,并把把我们需要的json数据作为参数传入。在服务器端,当req.params参数中带有callback属性时,则把数据作为callback的参数执行,并拼接成一个字符串后返回。 

2.JSONP和AJAX对比

JSONP和AJAX相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。但AJAX属于同源策略,JSONP属于非同源策略(跨域请求)

3.JSONP优缺点

- 优点:兼容性好,在很古老的浏览器中也可以用,简单易用,支持浏览器与服务器双向通信。 
- 缺点:只支持GET请求,且只支持跨域HTTP请求这种情况(不支持HTTPS

4.JSONP的代码实现

<script>
    var script = document.createElement('script');
    script.type = 'text/javascript';
    // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);
    // 回调执行函数
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>

后端node代码实现:

router.get('/article-list', (req, res) => {
  let data = {
    message: 'success!',
    name: req.query.name,
    age: req.query.age
  }
  const fn = req.query.callback
  data = JSON.stringify(data)
  res.end(fn + '(' + data + ')');
}

2. 处理跨域方法二 CORS


上面jsonp的方式已经暴露了一个巨大的缺点,那就是无法解决post请求的跨域。因此,我们更多的是使用cors来解决跨域问题,它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法,实际上就是在响应头添加允许跨域的源(意思就是允许去哪些源地址去请求这个服务器)

核心思想:在服务器端通过检查请求头部的origin,从而决定请求应该成功还是失败。具体的方法是在服务端设置Response Header响应头中的Access-Control-Allow-Origin为对应的域名,实现了CORS(跨域资源共享),这里出于在安全性方面的考虑就是尽量不要用 *,但对于一些不重要的数据则随意,例如图片。


前端什么也不用做
后端需要开启cors
 

3、处理跨域方法三——WebSocket

Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

4、处理跨域方法四——postMessage

如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。

5、处理跨域方法五vue-cli代理转发

浏览器是禁止跨域的,但是服务端不禁止,在本地运行npm run dev等命令时实际上是用node运行了一个服务器,因此proxyTable实际上是将请求发给自己的服务器,再由服务器转发给后台服务器,做了亦曾代理,因为不会出现跨域问题。

如果后端jsonp也不弄, cors也不弄, 就给你个接口地址

我们可以在本地弄个服务器, 然后用服务器请求后台服务器接口地址

但是vuecli脚手架, 启动了一个webpack开发服务器, 它就能做代理转发

而且前端和这个服务器是同源的都是8080端口
需要修改webpack开发服务器的配置即可

在前端服务和后端接口服务之间 架设一个中间代理服务,它的地址保持和前端服务一致,那么:

代理服务和前端服务之间由于协议域名端口三者统一不存在跨域问题,可以直接发送请求

代理服务和后端服务之间由于并不经过浏览器没有同源策略的限制,可以直接发送请求

这样,我们就可以通过中间这台服务器做接口转发,在开发环境下解决跨域问题,看起来好像挺复杂,其实vue-cli已经为我们内置了该技术,我们只需要按照要求配置一下即可。
 

devServer: {
    proxy: {
      // http://c.m.163.com/nc/article/headline/T1348647853363/0-40.html
      '/api': { // 请求相对路径以/api开头的, 才会走这里的配置
        target: 'http://c.m.163.com', // 后台接口域名 我们要代理的真实的接口地址
        changeOrigin: true, // 改变请求来源(欺骗后台你的请求是从http://c.m.163.com)
        pathRewrite: {
          '^/api': '' // 因为真实路径中并没有/api这段, 所以要去掉这段才能拼接正确地址转发请求
        }
      }
    }
  }

 axios请求的代码

axios({
    url: '/api/nc/article/headline/T1348647853363/0-40.html'
})

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
JavaScript CSS面试题是一种常见的面试题目,用于测试面试者对JavaScript和CSS的基本知识的掌握程度。这些问题涵盖了JavaScript的基本数据类型、基本规范、继承方式、作用域链、this关键字、eval函数、window对象、document对象、null和undefined的区别、事件机制、闭包、严格模式、对象判断、new操作符、JSON、延迟加载、跨域问题、页面编码、模块化开发、call和apply方法、DOM操作、数组方法、内存泄漏、Cookie隔离、Flash与Ajax交互、XML与JSON的区别等等。这些问题可以帮助面试者展示他们对JavaScript和CSS的理解和应用能力。\[1\]同时,CSS3中引入了双冒号(::)用于伪元素,而单冒号(:)用于伪类。伪元素和伪类的区别在于伪元素是在当前规范中引入的,而伪类是已经存在的。伪元素的插入内容可以出现在其他内容前或后,而伪类则不具备这个功能。\[2\]此外,为了清除浮动,可以在结尾处添加一个空的div标签,并使用clear:both属性来清除浮动,让父级div自动获取高度。但是这种方法会增加无意义的标签,语义化差。\[3\] #### 引用[.reference_title] - *1* *2* [148道 CSS 与 JavaScript 基础面试题](https://blog.csdn.net/QXXXD/article/details/115460560)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [CSS+JS面试题](https://blog.csdn.net/m0_47224321/article/details/121240648)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

燕穗子博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值