跨域理论知识

跨域

  1. 跨域是针对浏览器环境,脱离浏览器环境则不存在该问题

同源跨域

同源

  1. 协议,域名(地址),端口,三者都相同就称之为同源
  2. 同源策略是一种安全协议,指一段脚本只能读取来自同一来源的窗口和文档的属性
  3. 不同源:协议,域名(地址),端口,三者有一个不一样就称之为不同源

跨域

  1. 跨域:不同源的网站之间互相发送请求,称之为跨域访问
  2. 浏览器默认是跨域访问的,虽然被限制了,但是在开发中不可避免会出现跨域访问,为了解决跨域访问
    1. 在服务器后台设置允许跨域访问:header(‘Access-Control-Allow-Origin: *’),表示允许任何客户端环境都可以访问该服务器
    2. 在服务器后台设置允许跨域访问:header(‘Access-Control-Allow-Origin: http://xx.xx.xx:xxxx’),设置白名单,只有白名单中的客户端环境可以访问改服务器
  3. 此方法只有html5才支持,为了兼容低版本浏览器,就使用另外一种解决方案jsonp

跨域解决方案

Jsonp

  1. json是一种数据格式,而jsonp是用来解决跨域获取数据的一种解决方案

  2. jsonp原理:

    1. jsonp就是利用了script标签的src属性支持跨域获取资源

    2. script标签后面中src属性写上需要请求页面的网址,并且发送一个方法的方法名到服务器,如:

      <!-- 请求地址为:http://localhost:5880/dev/api/system/router -->
      <!-- 方法名为:callback -->
      <scipt src="http://localhost:5880/dev/api/system/router?method=callback"></script>"></script>
      
      // 也可通过js动态创建script标签进行请求
      const jsonp = (url, name) => {
        const script = document.createElement('script');
        script.src = `${url}?method=${name}`;
        document.body.appendChild(script);
        // script加载完毕后移除标签
        script.onload = () => {
          script.remove();
        };
      };
      
      // 调用
      jsonp('http://localhost:5880/dev/api/system/router', 'callback');
      
    3. 服务器接收到方法名之后,拼接一个方法的调用,在方法的参数中传入需要给浏览器的数据,响应格式为:callback(json数据)

      // 严重影响服务器的正常响应格式
      const script = `callback(${json})`
      res.header('content-type', 'application/javascirpt').send(script)
      
    4. 返回给浏览器,浏览器把数据当做js进行解析,解决跨域问题

      // 调用js中的callback方法
      const callback = (data) => {
        console.log(data) // 获得响应结果
      }
      
  3. 缺点:

    • 只支持get请求方式
    • 严重影响服务器的正常响应格式

CORS

  1. CORS:基于http1.1的一种跨域解决方案,跨域资源共享
  2. 实现原理:如果浏览器要跨域访问服务器的资源,需要获得服务器的允许
  3. 一个请求可以附带很多信息,从而会对服务器造成不同程度的影响,针对不同的请求,CORS规定了三种不同的交互模式
    1. 简单请求
    2. 需要预检的请求
    3. 附带身份凭证的请求
简单请求
简单请求的判定
  1. 当请求同时满足以下条件时,浏览器会认为它是一个简单请求:

    1. 请求方法属于下面的一种
      • get
      • post
      • head
    2. 请求头仅包含安全的字段,常见的安全字段如下:
      • Accept
      • Accept-Language
      • Content-Language
      • Content-Type
      • DPR
      • Downlink
      • Save-Data
      • Viewport-Width
      • Width
    3. 请求头包含Content-Type,仅限下面的值之一:
      • text/plain
      • multipart/form-data
      • application/x-www-form-urlencoded
  2. 如以下示例:

    // 简单请求
    fetch("http://crossdomain.com/api/news");
    
    // 请求方法不满足要求,不是简单请求
    fetch("http://crossdomain.com/api/news", {
      method:"PUT"
    })
    
    // 加入了额外的请求头,不是简单请求
    fetch("http://crossdomain.com/api/news", {
      headers:{
        a: 1
      }
    })
    
    // 简单请求
    fetch("http://crossdomain.com/api/news", {
      method: "post"
    })
    
    // content-type不满足要求,不是简单请求
    fetch("http://crossdomain.com/api/news", {
      method: "post",
      headers: {
        "content-type": "application/json"
      }
    })
    
简单请求的交互规范
  1. 当浏览器判定某个ajax跨域请求是简单请求时,会发生以下的事情
    1. 请求头中会自动添加Origin字段,origin:正进行跨域请求的源地址
    2. 服务器响应头中应包含Access-Control-Allow-OriginAccess-Control-Allow-Origin的值为
      • *:表示我很开放,什么人我都允许访问
      • 具体的源:比如http://my.com,表示只允许该源地址访问
需要预检的请求
  1. 简单的请求对服务器的威胁不大,若浏览器不认为这是一种简单请求,就会按照下面的流程进行:
    1. 浏览器发送预检请求,询问服务器是否允许
    2. 服务器允许
    3. 浏览器发送真实请求
    4. 服务器完成真实的响应
预检请求的交互规范
  1. 浏览器发送预检请求,询问服务器是否允许
    1. 预检请求没有请求体,为以下特征:
      1. 请求方法为OPTIONS
      2. 没有请求体
      3. 请求头中包含
        • Origin:请求的源,和简单请求的含义一致
        • Access-Control-Request-Method:后续的真实请求将使用的请求方法
        • Access-Control-Request-Headers:后续的真实请求设置的请求头
  2. 服务器允许
    1. 服务器收到预检请求后,可以检查预检请求中包含的信息,若允许该的请求,需要响应以下消息格式
      1. 不需要响应任何消息体
      2. 响应头中包含
        • Access-Control-Allow-Origin:和简单请求一样,表示允许的源
        • Access-Control-Allow-Methods:表示允许的后续真实的请求方法
        • Access-Control-Allow-Headers:表示允许改动的请求头
        • Access-Control-Max-Age:告诉浏览器,多少秒内,对于同样的请求源、方法、头,都不需要再发送预检请求
  3. 浏览器发送真实请求
    1. 预检被服务器允许后,浏览器就会发送真实请求
  4. 服务器响应真实请求
附带身份凭证的请求
  1. 默认情况下,ajax的跨域请求并不会附带cookie,某些需要权限的操作就无法进行
  2. 解决:通过简单的配置就可以实现附带cookie
    1. 响应头添加:Access-Control-Allow-Credentials: true
  3. 注意:对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为*
补充
  1. 在跨域访问时,JS只能拿到一些最基本的响应头,如:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置响应头:Access-Control-Expose-Headers,如下:

    Access-Control-Expose-Headers: authorization, a, b
    
CORS中间件使用
  1. 安装:npm install cors
  2. 文档地址:[GitHub - expressjs/cors: Node.js CORS middleware](https://github.com/rs/cors)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

喜欢代码的新之助

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

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

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

打赏作者

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

抵扣说明:

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

余额充值