同源策略(跨域)-解决方法

138 阅读3分钟

什么是跨域

请求如果触发了同源策略的话,会出现跨域的情况

最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"。

  • 协议相同

  • 域名相同

  • 端口相同

举例来说, www.example.com/dir/page.ht… 这个网址,协议是http:// ,域名是 www.example.com ,端口是80 (默认端口可以省略)。它的同源情况如下。

目的

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网

站的 Cookie,会发生什么?

很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来 保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

限制范围

随着互联网的发展,"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制。

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) A JAX 请求不能发送。

虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。下面,我将详细介绍,如何规避上面三种限制。

解决方案

JSONP

根据之前的结局方案,需要前后端配合

静态网页的html

<!--
        因为 服务器内做了配置, 只要是以 '/static' 开头的访问都会去到 '/client' 这个目录内

        具体配置需要查看 index.js 1.1 步 开启静态资源
     -->

    <script>
      function qwe(res) {
        console.log('我是这个函数的内部代码')
        console.log(res)
      }
    </script>

 
    <script src="http://localhost:8081/a?callback=qwe">
      //qwe是函数

    </script>

需要接口服务器配合

server.get('/a', (req, res) => {
   const { callback } = req.query
  // console.log(`${callback}({code:1,msg:'请求成功'})`)

  res.send(`${callback}({code:1,msg:'请求成功'})`)

})

CORS跨域

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的

AJAX通信没有差别,代码完全一样。浏览器一旦发现A JAX请求跨源,就会自动添加一些附加的头信息,

有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

注意:写到接口服务器上 给谁添加CORS方法

//1.导入第三方库
const cors = require('cors')
//2.使用
server.use(cors())
const express = require('express')
//1.导入第三方库
const cors = require('cors')

const server = express()
//2.使用
server.use(cors())

server.get('/list', (req, res) => {
  res.send({
    code: 1,
    msg: '请求成功'
  })
})

server.post('/info', (req, res) => {
  res.send({
    code: 1,
    msg: '请求成功'
  })
})

server.listen('8081', () => console.log('接口服务器开启成功'))

axios

主要思路

通过服务其与服务器之间传递 就不会触发同源策略

比如8080 访问 8081 会触发同源策略

axios 访问自己的服务器 自己的服务器 去访问8081服务器 拿到值之后 通过自己的服务器返回给自己的8080

请求浏览器8080

const express = require('express')
const axios = require('axios')
const server = express()

server.use('/static', express.static('./client'))
server.get('/list', (req, res) => {
  console.log('如果我执行了, 说明前端的代码是请求我的')
  /**
   *  node 中 需要借助 axios 帮助我们发送请求, 第三方包的流程: 下载 导入 按照文档使用
   *
   *  安装命令:  npm i axios
   */
  axios({
    method: 'GET',
    url: 'http://localhost:8081/list'
  }).then(result => {
    // console.log(result.data)
    res.send(result.data)
  })
})

server.listen('8080', () => console.log('静态资源服务器开启成功'))

**不进行跨域 **

// 前端的代码, 发送一个请求

function myAjax1() {
  const xhr = new XMLHttpRequest()
  // xhr.open("GET", "http://localhost:8081/list");
  xhr.open('GET', '/list')//通过自己的服务其拿
  xhr.onload = function () {
    console.log(JSON.parse(xhr.responseText))
  }
  xhr.send()
}
myAjax1()