前端面试系列之跨域

前端跨域问题相信很多朋友都遇到过,很多时候我们都是直接交给后端来解决。那么为什么会出现跨域问题呢?后端是如何解决跨域问题?

什么是跨域?

广义的跨域包括:

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

狭义的跨域:指浏览器同源策略限制的请求。我们通常所说的也指的是这种。

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

如果两个 URL 的 protocol、port (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。简单来说就是指"协议+域名+端口"三者都相同,如果有一个不同都会导致跨域,即使两个域名指向同一个ip也不会例外。以 http://store.company.com/goods/list为例

URL 结果 原因
http://store.company.com/goods/detail 同源 只有路径不同
http://store.company.com/my/info 同源 只有路径不同
https://store.company.com/goods/list 失败 协议不同
http://store.company.com:81/goods/list 失败 端口不同 ( http:// 默认端口是80)
http://news.company.com/goods/list 失败 主机不同

跨域的方法

跨域的方法很多,网上案例很多 常见的大概有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中间件代理跨域

当然,在日常工作中,我们使用最多的还是jsonpCORS两种,本文也只介绍着两种方式。

1.jsonp跨域

jsonp跨域的原理很简单,就是利用script标签不受同源策略限制这一特点来实现的。这也是jsonp的为什么只支持get请求,而不支持post请求的原因。通过动态创建script标签连接服务端,服务端通过函数执行的方式将data传递给前端。
代码以原生js为例:

<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来解决跨域问题。

跨源资源共享 (CORS) (或通俗地译为跨域资源共享)是一种基于HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域,协议和端口),这样浏览器可以访问加载这些资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的"预检"请求。在预检中,浏览器发送的头中标示有HTTP方法和真实请求中会用到的头。

以fetch请求为例, fetch('http://localhost:10086/cors/test1')

scene 1

当我们什么都不做时,此时我们发现,network弹出如下错误:
在这里插入图片描述

根据报错提示设置mode,于是我们设置如下fetch('http://baidu.com/x',{mode:'no-cors'}),此时结果如下在这里插入图片描述
network不再报错了,然而没有返回值,status居然是0。
原来 no-cors并不是绕过跨域的意思,这也是新手常犯的一个错误

no-cors 保证请求对应的 method 只有 HEAD,GET 或 POST 方法,并且请求的 headers 只能有简单请求头 (simple headers)。如果 ServiceWorker 劫持了此类请求,除了 simple header 之外,不能添加或修改其他 header。另外 JavaScript 不会读取 Response 的任何属性。这样将会确保 ServiceWorker 不会影响 Web 语义(semantics of the Web),同时保证了在跨域时不会发生安全和隐私泄露的问题。

原来,我们需要在服务端设置头信息Access-Control-Allow-Origin,可以带*,代表wildcard,任何origin都合法,但是有一定的安全风险, 也可以设置具体的origin,本例子则设置为http://localhost:4000。如果想带多个的话呢?抱歉,没有办法,只能设置单独一个,或者全部都成功。<

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值