前端跨域

166 阅读3分钟

前端跨域

什么是跨域

跨域指的是:浏览器不能执行其他网站的脚本,从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。跨域是由浏览器的同源策略造成的,是浏览器施加的安全限制。a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的。

跨域原理

image.png

当发起跨域请求时,会卡在接口响应阶段,由于浏览器的同源策略,实际正常返回,但是不能被浏览器响应。

什么是同源策略

同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;

http:// https:// 不是同源 a.com b.com 不是同源 a.com:80 a.com:8000 不是同源

同源策略详情(可以略过)

同源策略,它是由Netscape提出的一个著名的安全策略

当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面

当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,

即检查是否同源,只有和百度同源的脚本才会被执行。 [1] 

如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。

同源策略的优势

跨域解决方式

  1. jsonp跨域 目前几乎不用

    // 接口返回
    router.get('/testA', function (req, res, next) {
      let { callback } = req.query
      res.send(callback+"('123')")
    });
    
    // 发送请求
    <script>
        window.callback = function (data) {
           alert(data)  // 弹出123
        }
        let script = document.createElement('script')
        script.src = `http://test.a.com:3333/testA?name=1&callback=callback`
        document.body.appendChild(script)
    </script>
    
  2. nginx反向代理
    使用场景:将前端静态页面部署到nginx服务器上

    原理分析:

    image.png

  3. cors
    ** linux环境修改 /etc/hosts文件 ** 10.167.15.207 是本机ip,这里主要作用是模拟一个域名,只在本地生效

image.png 使用场景:服务端做跨域处理,前端无需修改 > DEMO 场景 使用两个express搭建的前端服务
> 使用jquery ajax发送前端请求
```

1. express 允许返回HTML
2. 创建html文件
//test.a.com
router.get('/testA', function(req, res, next) {
  res.setHeader('Access-Control-Allow-Origin',"*")  // cors跨域处理
  res.send({
    name:'123'
  });
});

//test.b.com
 <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.js"></script>
<script>
    $.ajax({
        url:'http://test.a.com:3333/testA',
        method:'get',
        success: function(res) {
            console.log(res)
        },
        error: function(err){
            console.log(err)
        }
    })

```

6. http-proxy
使用场景:中间层做代理,进行转发,跟nginx相同。

源的更改

满足某些限制条件的情况下,页面是可以修改它的源。脚本可以将 document.domain 的值设置为其当前域或其当前域的父域。如果将其设置为其当前域的父域,则这个较短的父域将用于后续源检查。

    document.domain = "company.com";

源 == 域 / 子域和父域的关系

使用 document.domain 来允许子域安全访问其父域时,您需要在父域和子域中设置 document.domain 为相同的值。这是必要的,即使这样做只是将父域设置回其原始值。不这样做可能会导致权限错误。

换句话说:子域可以获取父域的请求头信息 (联合登录时可以利用同域来解决)

前端允许的跨域有~

  1. script
  2. link
  3. img
  4. video
  5. @font-face
  6. iframe