zoukankan      html  css  js  c++  java
  • 跨域方式实现原理

    跨域方式实现原理

     同源策略限制内容有:

    • Cookie、LocalStorage等存储性内容
    • AJAX 请求被浏览器拦截

    但是有三个标签是允许跨域加载资源:

    •  <img src=xxx>
    • <link href=xxx>
    • <script src=xxx>

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

    协议端口号 造成的跨域是前端无法解决的

    跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了

    跨域解决方案

    1) JSONP

      原理:利用 <script> 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。

        优点:JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题

      缺点: 仅支持get方法,参数需要拼接起来,不够安全

    H5

        function jsonp({
            url,
            params,
            callback
        }) {
            return new Promise((resolve, reject) => {
                let script = document.createElement('script')
                window[callback] = data => {
                    resolve(data);
                }
                params = {
                    ...params,
                    callback
                }
                Object.keys(params).forEach(function (value, index) {
                    script.src += index ? `&${value}=${params[value]}` : `${url}?${value}=${params[value]}`
                })
                document.body.appendChild(script)
            })
        }
        jsonp({
            url: 'http://localhost:3000/wel',
            params: {
                id: 3,
                name: 'Kobe'
            },
            callback: 'show'
        }).then((data) => {
            console.log(data)
        })

    node服务端

    var express = require('express');
    var app = express();
    
    
    // 接口
    app.get('/', (req, res) => res.send('hello word!'));
    app.get('/wel', (req, res) => {
      let {
        id,
        name,
        callback
      } = req.query
      let obj = {
        name: 'chen',
        height: 30,
        code: -1
      }
      if (id && name) {
        obj = {
          name: 'li',
          height: 50,
          code: 1
        }
      }
      return res.send(`${callback}(${JSON.stringify(obj)})`)
    });
    
    app.listen(3000, () => console.log('listening on port 3000'));

    2) CORS(参考文章:HTTP访问控制(CORS))

      跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。(MDN描述)

       功能描述 :跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

      node服务端

    let whitList = ['http://localhost:8080','http://localhost:8081'] //设置白名单
    app.use(function(req, res, next) {
      let origin = req.headers.origin
      console.log(origin)
      if (whitList.includes(origin)) {
        // 设置哪个源可以访问我
        res.setHeader('Access-Control-Allow-Origin', origin)
        // 允许携带哪个头访问我
        res.setHeader('Access-Control-Allow-Headers', 'x-requested-with')
        // 允许哪个方法访问我
        res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
        // 允许携带cookie
        res.setHeader('Access-Control-Allow-Credentials', true)
        // 预检的存活时间
        res.setHeader('Access-Control-Max-Age', 36)
        // 允许返回的头
        res.setHeader('Access-Control-Expose-Headers', 'x-requested-with')
        if (req.method === 'OPTIONS') {
          res.end() // OPTIONS请求不做任何处理
        }
      }
      next()
    })
    app.put('/index', function(req, res) {
      res.setHeader('x-requested-with', 'origin') //返回一个响应头,后台需设置
      const obj={
        id:1,
        name:'Kobe',
        code:1,
      }
      return res.send(`${JSON.stringify(obj)}`)
    })

    H5

        let xhr = new XMLHttpRequest();
          xhr.withCredentials = true; // 前端设置是否带cookie
          xhr.open("PUT", "http://localhost:3000/index", true);
          xhr.setRequestHeader("x-requested-with", "origin");
          xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
              if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
                console.log(xhr.response);
                //得到响应头,后台需设置Access-Control-Expose-Headers
                console.log(xhr.getResponseHeader("x-requested-with"));
              }
            }
          };
          xhr.send();

      

  • 相关阅读:
    leetcode 78. 子集 JAVA
    leetcode 91. 解码方法 JAVA
    leetcode 75. 颜色分类 JAVA
    leetcode 74 搜索二维矩阵 java
    leetcode 84. 柱状图中最大的矩形 JAVA
    last occurance
    first occurance
    classical binary search
    LC.234.Palindrome Linked List
    LC.142. Linked List Cycle II
  • 原文地址:https://www.cnblogs.com/dajuyiding/p/11384782.html
Copyright © 2011-2022 走看看