• 跨域方式实现原理


    跨域方式实现原理

     同源策略限制内容有:

    • 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();

      

  • 相关阅读:
    sql左外连接、右外连接、group by、distinct(区别)、intersect(交叉)、通配符、having
    nvarchar,varchar 区别
    链家笔试链家——找寻最小消费获取最大平均分java
    利用SpringAOP 实现 日志输出
    AOP 学习笔记
    Spring AOP中pointcut expression表达式解析
    基于@Aspect的AOP配置
    URI 中特殊字符处理
    给电脑设置视力保护色
    Spring不支持依赖注入static静态变量
  • 原文地址:https://www.cnblogs.com/dajuyiding/p/11384782.html
Copyright © 2020-2023  润新知