跨域三种种方法

135 阅读4分钟

浏览器的同源策略

  •  window.origin或者location.origin可以得到当前源
     如果两个url的
     协议
     域名
     端口号
     完全一致,那么这两个url就是同源
    
  • 同源策略定义

     浏览器规定
     如果js运行在源A里,那么就只能获取源A的数据
     不能获取源B的数据,即不允许跨域
    

实现跨域的两种方法

CORS (Cross-Origin Resource Sharing,跨域资源共享)是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应

  • **Access-Control-Allow-Origin** 响应头指定了该响应的资源是否被允许与给定的origin共享。
 //server.js文件
 //cors (前端和后端合作实现)
 var http = require('http')// 引入 http 模块,用来创建 http 服务器
 var fs = require('fs')// 引入 fs 模块,用来操作文件系统
 var url = require('url')// 引入 url 模块,用来解析 url
 var port = process.argv[2]// 拿到执行此脚本命令的第二个参数(即为 port),如 node server.js 8888,那么 port = 8888
 ​
 if (!port) {
     console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
     process.exit(1)
 }
 ​
 var server = http.createServer(function (request, response) {
     // 解析 url 拿到解析后的对象,形如 parsedUrl 图(见下文)
     var parsedUrl = url.parse(request.url, true)
     // 带 query 的 path,见下文 pathWithQuery
     var pathWithQuery = request.url
     var queryString = ''
     // 判断是否带 query
     if (pathWithQuery.indexOf('?') >= 0) {
         // 带 query 的话则拿到它
         queryString = pathWithQuery.substring(pathWithQuery.indexOf('?'))
     }
     var path = parsedUrl.pathname
     var query = parsedUrl.query
     // 拿到请求方法
     var method = request.method
 ​
     /******** 从这里开始看,上面不要看 ************/
 ​
     console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)
     // 处理 / 路由
     if (path === '/index.html') {
         // 设置响应状态码为 200
         response.statusCode = 200
         // 设置响应头 content-type 字段
         response.setHeader('Content-Type', 'text/html;charset=utf-8')
         let string = fs.readFileSync('./public/index.html').toString()
         // 设置响应体内容
         response.write(string)
         // 结束并响应请求
         response.end()
     } else if (path === '/qq.js') {
         response.statusCode = 200
         response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
         response.write(fs.readFileSync('./public/qq.js'))
         response.end()
     } else if (path === '/qq.json') {
         response.statusCode = 200
         response.setHeader('Content-Type', 'text/json;charset=utf-8')
         //cors设置允许访访的源
         response.setHeader("Access-Control-Allow-Origin", "http://www.frank.com:9903")
         let string = fs.readFileSync('./public/qq.json')
         response.write(string)
         response.end()
     } else if (path === "/jsonp.js") {
         response.statusCode = 200
         response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
         const string = fs.readFileSync('./public/jsonp.js').toString()
         const name = query.callBake
         const data = fs.readFileSync('./public/qq.json').toString()
         let string1 = string.replace("{ { data } }", data).replace("xxx", name)
         response.write(string1)
         response.end()
     } else {
         // 兜底,除了上面两种路由,其它路由都走此逻辑
         response.statusCode = 404
         response.setHeader('Content-Type', 'text/json;charset=utf-8')
         response.write(`你输入的路径不存在对应的内容`)
         response.end()
     }
     /******** 代码结束,下面不要看 ************/
 })
 // 监听 port 端口,只有执行了此语句才算启动了服务
 server.listen(port)
 // 命令行打印日志
 console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)
 ​

jspn跨域

 node.js后端设置
 json原理(前端和后端合作实现)
 设置好函数
 后台使用js文件调用函数,拿到数据
 在引入js文件,解决跨域
 缺点只能用GET请求,没有响应码
 后端设置
 //处理路由
  if (path === "/jsonp.js") {
     //设置响应状态码
   response.statusCode = 200
      //设置响应头Content-Type
   response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
     //读取json文件内容
    const string = fs.readFileSync('./public/jsonp.js').toString()
    //函数名
    const name = query.callBake
    //读取数据
    const data = fs.readFileSync('./public/qq.json').toString()
    //把数据写入json.js,并且设置函数名
    let string1 = string.replace("{ { data } }", data).replace("xxx", name)
         response.write(string1)
         response.end()
     }
 ​
 前端代码
 //jsonp实现跨域
 const random = Math.random()
 window[random] = (data) => {
     console.log(data)
 }
 const script = document.createElement('script')
 script.src = `http://www.qq.com:8888/jsonp.js?callBake=${random}`
 script.onload = () => {
     script.remove()
 }
 document.body.appendChild(script)

在vue-cli项目中使用反向代理

安装axios

 npm install axios

在项目中引入axios

import axios from 'axios'
Vue.prototype.$axios = axios

使用axios发起get请求

this.get(url).then(response=>{
    console.log(response)
}).catch(error=>{
    console.log(err)
})
axios.get(url, {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  })
  .then(function () {
    // always executed
  });  

使用axios发起post请求

axios.post(url, {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
使用axios时需要使用反向代理解决跨域问题

在vue项目开发阶段,常常会碰到跨域请求的问题,我们能使用反向代理解决

解决方法:

\1. 在项目文件夹下创建 vue.config.js配置文件

// vue.config.js文件
module.exports = {
  lintOnSave: false,
    //添加如下代码
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:8080', //设置你调用的接口域名和端口号 别忘了加http
        changeOrigin: true,  //如果接口跨域,需要进行这个参数配置
        secure: false,  // 如果是https接口,需要配置这个参数
        pathRewrite: {
          '^/api': ''//这里理解成用‘/api’代替target里面的地址,后面组件中我们调用接口时直接用api代替
        }
      }
    }
  }
}

使用在main.js

   // 引入axios
   import axios from "axios"
   // 给vue原型添加一个属性$axios 其属性值为axios
   Vue.prototype.$axios = axios;
   // 给axios设置一个默认请求地址 这样请求数据时/api可以省略不写 方便后期优化
   axios.defaults.baseURL = "/api";

发起get请求

   this.$axios.get('/api/')
  .then(response => {
    //成功返回
    console.log(response)
    console.log(response.data);
    this.obj = response.data
  })
  .catch(error => {
    //失败返回
    console.log(error);
  });