前端之同源策略和跨域问题解决方法

知识点

  • 同源策略
  • 跨域
  • JSONP
  • CORS(服务端支持)
  • document.domain
  • window.name
  • window.postMessage方法
  • iframe加form
  • 代理 Nginx配置

同源策略

  • ajax 请求时,浏览器要求当前网页和server必须同源(安全)
  • 同源:协议,域名,端口,三者必须一致

同源策略详情请点击存在必要性:浅谈CSRF攻击

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

跨域

跨域,指的是从一个域名去请求另外一个域名的资源。即跨域名请求!跨域时,浏览器不能执行其他域名网站的脚本,是由浏览器的同源策略造成的,是浏览器施加的安全限制。

跨域的严格一点来说就是只要协议,域名,端口有任何一个的不同,就被当作是跨域。

加载图片 CSS JS 可无视同源策略

提示:
我们有时候就会引入一些cdn 的js和css等,这些地址肯定不是同源的,但却可以使用。
另外,有些图片如果做了防盗链限制(服务端上的处理)的话,就不能使用。
感兴趣的请点击我的另一篇博客:图片视频等资源中转,用nodejs解决防盗链问题

Oh my god! 那为什么图片 CSS JS 可无视 同源策略???

前端之同源策略和跨域问题解决方法_第1张图片
浏览器这样做,都是有一定的考虑的,都是为了有一些功能,比如说:

  • 可用于统计打点,可使用第三方统计服务
  • 代码示例接收方:

    
    
    
    

    No.6 iframe加form

    JSONP只能发送GET请求,因为本质上script加载资源就是GET。如果要发送POST请求可以如下

    后端代码:

    // 处理成功失败返回格式的工具
    const {successBody} = require('../utli')
    class CrossDomain {
      static async iframePost (ctx) {
        let postData = ctx.request.body
        console.log(postData)
        ctx.body = successBody({postData: postData}, 'success')
      }
    }
    module.exports = CrossDomain
    

    前端代码:

    const requestPost = ({url, data}) => {
      // 首先创建一个用来发送数据的iframe.
      const iframe = document.createElement('iframe')
      iframe.name = 'iframePost'
      iframe.style.display = 'none'
      document.body.appendChild(iframe)
      const form = document.createElement('form')
      const node = document.createElement('input')
      // 注册iframe的load事件处理程序,如果你需要在响应返回时执行一些操作的话.
      iframe.addEventListener('load', function () {
        console.log('post success')
      })
    
      form.action = url
      // 在指定的iframe中执行form
      form.target = iframe.name
      form.method = 'post'
      for (let name in data) {
        node.name = name
        node.value = data[name].toString()
        form.appendChild(node.cloneNode())
      }
      // 表单元素需要添加到主文档中.
      form.style.display = 'none'
      document.body.appendChild(form)
      form.submit()
    
      // 表单提交后,就可以删除这个表单,不影响下次的数据发送.
      document.body.removeChild(form)
    }
    // 使用方式
    requestPost({
      url: 'http://localhost:9871/api/iframePost',
      data: {
        msg: 'helloIframePost'
      }
    })
    

    No.7 代理 Nginx配置

    server{
        # 监听9099端口
        listen 9099;
        # 域名是localhost
        server_name localhost;
        #凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 
        location ^~ /api {
            proxy_pass http://localhost:9871;
        }    
    }
    
    // 请求的时候直接用回前端这边的域名http://localhost:9099,这就不会跨域,然后Nginx监听到凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 
    fetch('http://localhost:9099/api/iframePost', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        msg: 'helloIframePost'
      })
    })
    

    其他有趣的跨域问题

    • canvas操作图片的跨域问题
      参考地址

    前端之同源策略和跨域问题解决方法_第3张图片帅气逼人的家伙们,赏个赞呗~ _(¦3」∠)_ 前端知识体系 目录结构

你可能感兴趣的:(前端,跨域,前端)