JavaScript 同源策略和跨域

同源策略与跨域

同源策略:url 的 协议、IP、端口都相同。

跨域:同源策略不满足。

<img> <link><script>:天然允许跨域加载资源

请求跨域解决方案

  • jsonp

    • 原理:利用 <script>,标签没有跨域限制的漏洞,使得网页可以得到从其他来源动态产生的 JSON 数据(前提是服务器支持)
    • 优点:实现简单,兼容性好
    • 缺点:仅支持 GET 方法,容易受到 XSS 攻击
  • CORS

    • 原理:服务器端设置 Access-Control-Allow-Origin 以开启 CORS。该属性表示哪些域名可以访问资源,如设置通配符则表示所有网站均可访问

    • 示例

      // app.js
      
      var app = express();
      // CORS跨域-------------------------------------------------------------------------------------
      // CORS:设置允许跨域中间件
      var allowCrossDomain = function (req, res, next) {
        // 设置允许跨域访问的 URL(* 表示允许任意 URL 访问)
        res.header("Access-Control-Allow-Origin", "*");
        // 设置允许跨域访问的请求头
        res.header("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept,Authorization");
        // 设置允许跨域访问的请求类型
        res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
        // 设置允许服务器接收 cookie
        res.header('Access-Control-Allow-Credentials', 'true');
        next();
      };
      app.use(allowCrossDomain);
      
  • WebSocket

    • 原理:Websocket 是 HTML5 规范提出的一个应用层的全双工协议,适用于浏览器与服务器进行实时通信场景

    • 示例

      // 在 a 网站直接创建一个 WebSocket 连接,连接到 b 网站即可,
      // 然后调用 WebScoket 实例 ws 的 send() 函数向服务端发送消息,监听实例 ws 的 onmessage 事件得到响应内容。
      var ws = new WebSocket("ws://b.com");
      ws.onopen = function(){
        // ws.send(...);
      }
      ws.onmessage = function(e){
        // console.log(e.data);
      }
      
  • 代理转发

    • 原理:跨域是为了突破浏览器的同源策略限制,既然同源策略只存在于浏览器,那可以换个思路,在服务端进行跨域,比如设置代理转发。这种在服务端设置的代理称为“反向代理”,对于用户而言是无感知的

      另一种在客户端使用的代理称为 “正向代理”,主要用来代理客户端发送请求,用户使用时必须配置代理服务器的网址,比如常用的 VPN 工具就属于正向代理

    • 示例

      // 1、在 webpack 中代理
      // webpack.config.js
      // 当浏览器发起前缀为`/api`的请求时都会被转发到 `http://localhost:3000` 这个网址,
      // 然后将响应结果返回给浏览器。对于浏览器而言还是请求当前网站,但实际上已经被服务端转发。
      module.exports = {
        //...
        devServer: {
          proxy: {
            '/api': 'http://localhost:3000'
          }
        }
      };
      
      // 2、在 Nginx 中代理
      location /api {
          proxy_pass   http://localhost:3000;
      }
      

页面跨域解决方案

  • postMessage

    • 原理:HTML5 推出了一个新的函数 postMessage() 用来实现父子页面之间通信,而且不论这两个页面是否同源

    • 父页面传子页面示例

      // parent.html
      // 父页面地址:https://lagou.com
      var child = window.open('https://kaiwu.lagou.com');
      child.postMessage('hi', 'https://kaiwu.lagou.com');
      
      // child.html
      // https://kaiwu.lagou.com
      window.addEventListener('message', function(e) {
        console.log(e.data);
      }, false);
      
    • 子页面传父页面示例

      // child.html
      // 子页面地址:https://kaiwu.lagou.com
      window.opener.postMessage('hello', 'https://lagou.com');
      
      // parent.html
      // 父页面地址:https://lagou.com
      window.addEventListener('message', function(e) {
        console.log(e.data);
      }, false);
      
  • 改域

    • 原理:对于主域名相同,子域名不同的情况,可以通过修改 document.domain 的值来进行跨域。如果将其设置为其当前域的父域,则这个较短的父域将用于后续源检查

    • 示例

      有页面地址是 https://www.lagou.com/parent.html,在这个页面里面有一个 iframe,其 src 是 http://kaiwu.lagou.com/child.html

      这时只要把http://www.lagou.com/parent.htmlhttp://kaiwu.lagou.com/child.html 这两个页面的 document.domain 都设成相同的域名,那么父子页面之间就可以进行跨域通信了,同时还可以共享 cookie。

      但要注意的是,只能把 document.domain 设置成更高级的父域才有效果,

      例如在 http://kaiwu.lagou.com/child.html 中可以将 document.domain 设置成 lagou.com。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jackson Mseven

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

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

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

打赏作者

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

抵扣说明:

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

余额充值