转载于: https://www.bianchengquan.com/article/144302.html

1. 背景

前段时间想在群里搞个钉钉机器人定时提醒自己写周报,然而又碰到了跨域的情况,代码大致如下:

-- index.js --

import axios from 'axios'
function sxx () {
    axios.post('https://oapi.dingtalk.com/robot/send?XXXXXXXX', {
        msgtype: 'text',
        text: {
          content: '[sxx]: 我就是我, 是不一样的烟火'
        }
      })
}
sxx ()

-- webpack.config.js --

const path = require('path')
module.exports = {
    entry: './index.js',
    devServer: {
        host: '0.0.0.0',
        port: 8080
    },
    plugins: [
      new HtmlWebpackPlugin()
    ],
    output: {
      filename: 'main.js',
      path: path.resolve(__dirname, './dist')
    }
}

报错如下所示:

 

 

 

2. 回顾跨域的知识

对于跨域,MDN里的这篇文章:HTTP访问控制(CORS)讲的很清晰。截取里面非常经典的图片(见下图),我们在domain-a.com网站下,访问domain-b.com的资源(png图片和eot的字体),这两个资源就会跨域,此时浏览器可能会阻止这两个资源请求的发送,也可能是跨站请求正常发送,但返回结果被浏览器拦截,具体要看浏览器的实现。

 

 

那么,对应于我们本例中的跨域情况,我们是在0.0.0.0:8080下,访问oapi.dingtalk.com的资源,由于该请求跨域,浏览器直接阻止该请求的发送

 

凭啥你说是阻止了请求的发送?
通过charles可以看到post请求https://oapi.dingtalk.com/robot/send压根都没有发送,只是一个connect请求(况且若请求真的发送了,群里就会有钉钉机器人的消息了,返回的结果对我来说并没用)

 

 

3. 更改origin是否可以处理跨域

处理跨域常见的就是cors,服务器端设置Access-Control-Allow-Origin即可,可咱总不能让钉钉来添加吧?从跨域的原理看来,浏览器就是通过判断请求头中的origin结合请求的url来判断是否跨域的,那咱是不是可以更改origin来骗过浏览器?此时,咱们也有必要再了解下请求头中的host,origin字段:HTTP headers 之 host/referer/origin。于是,代码更改如下: -- index.js --

import axios from 'axios'
function sxx () {
    axios.post('https://oapi.dingtalk.com/robot/send?XXXXXXXX', {
        msgtype: 'text',
        text: {
          content: '[sxx]: 我就是我, 是不一样的烟火'
        }
      }, { headers: {'Origin': 'oapi.dingtalk.com'} })
}
sxx ()

然而,直接报错了...主要看第一个报错:Refused to set unsafe header "Origin"

 

 

 搜索下stack overflow大佬们对于该报错的解释,其中的第一条留言就很到位,出于安全性的考虑,header中的origin是人家浏览器设置的,咱们无法更改它(想想也是,要是人人都可以更改origin,浏览器的同源策略岂不形同虚设)

  

 

4. webpack的devServer.proxy处理了跨域

之前看到慕课网里dell老师讲的devServer.proxy可以代理开发环境中的url,尝试了下竟然绕过了跨域,请求成功了,代码更改如下:
-- index.js --

import axios from 'axios'
function sxx () {
    axios.post('/robot/send?XXXXXXXX', {
        msgtype: 'text',
        text: {
          content: '[sxx]: 我就是我, 是不一样的烟火'
        }
      })
}
sxx ()

-- webpack.config.js --

const path = require('path')
module.exports = {
    entry: './index.js',
    devServer: {
        host: '0.0.0.0',
        port: 8080,
        proxy: {
            '/robot': {
                target: 'https://oapi.dingtalk.com',
                secure: false, // 协议是https的时候必须要写
                changeOrigin: true
            }
        }
    },
    // ···省略了···太懒···
}

重点:添了changeOrigin: true后才可跨域,否则还是不行。那么重点就是理解为啥加上changeOrigin即可跨域

5. changeOrigin如何解决跨域

dell老师在视频里说changeOrigin字段是为了防止网站被爬数据,会验证请求的origin,若origin不是本网站的,则请求无法获得结果,看起来像是改变了header里的origin,但是刚不是尝试了咱们是无法更改origin的么?
查看文档中关于changeOrigin字段的描述:

changeOrigin: change the origin of the host header to the target url

还是不太明白,然后查看源码(在http-proxy/common.js中):

 

 

 从源码里可以清晰的看到,设置了changeOrigin只是更改了request请求中的host,并不是origin,那么更加奇怪了,到底是如何绕过跨域的呢? 

其实,devServer中的proxy就相当于charles进行url的代理,在sxx()执行后发送的请求是http://0.0.0.0:8080/robot/send?XXXXXXXX,我们是在0.0.0.0:8080下,当然不会限制这样的请求的发送,然后devServer的proxy通过配置将host更改为oapi.dingtalk.com,该请求就能正常进行,大致情况如下图所示:

 

 

 

6. charles模拟

为验证该想法,使用charles替换devServer.proxy进行url的代理,对于http://0.0.0.0:8080/robot/send?XXXXXXXX进行Breakpoint,更改该请求的host。 但是,又报错啦...如下图

 

 

 查询stack overflow中‘invalid Host header’,找到解决方法:只要在devServer中加个disableHostCheck: true即可。



posted @ 2021-10-08 15:59 demoblog 阅读(536) 评论(0) 推荐(0) 编辑
摘要: 转载于:https://my.oschina.net/winHerson/blog/176990 1、先查看是否有中文语言环境 locale -a结果会显示你的电脑已经安装的语言环境:en_US.ISO-8859-1 zh_CN.GBK 2、安装语言环境(root权限): dpkg-reconfig 阅读全文
posted @ 2021-03-08 20:56 demoblog 阅读(1585) 评论(0) 推荐(0) 编辑
摘要: 转载自:https://www.jianshu.com/p/d66421c826ae 本文参考了Fetch进阶指南 缘起 fetch网络请求没有timeout机制,也没有about机制。 而日常开发过程中,必定要对请求超时做处理,也要及时终止不需要的网络请求。 所以,就需要自己封装fetch来实现。 阅读全文
posted @ 2020-03-30 18:00 demoblog 阅读(918) 评论(0) 推荐(0) 编辑
摘要: 转载自: https://www.jianshu.com/p/7e60fc1be1b2 一、Pomise.all的使用 Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被rej 阅读全文
posted @ 2020-03-30 17:58 demoblog 阅读(302) 评论(0) 推荐(0) 编辑
摘要: 转载自: https://semaphoreci.com/community/tutorials/how-to-test-react-and-mobx-with-jest?utm_content=buffer15b42&utm_medium=social&utm_source=twitter.com 阅读全文
posted @ 2019-12-18 14:48 demoblog 阅读(528) 评论(0) 推荐(0) 编辑
摘要: 三个参数代表什么? %stmts是语句覆盖率(statement coverage):是不是每个语句都执行了? %Branch分支覆盖率(branch coverage):是不是每个if代码块都执行了? %Funcs函数覆盖率(function coverage):是不是每个函数都调用了? %Lin 阅读全文
posted @ 2019-12-18 11:08 demoblog 阅读(1818) 评论(0) 推荐(0) 编辑
摘要: 转载自 为Promise插上可取消的翅膀 阅读全文
posted @ 2019-12-09 21:38 demoblog 阅读(553) 评论(0) 推荐(0) 编辑
摘要: 转载: https://blog.csdn.net/qihoo_tech/article/details/91921777 奇技指南 身为前端,你真正深入理解了浏览器吗? 本文来自公众号奇舞周刊,作者李松峰,资深技术图书译者,翻译出版过40余部技术及交互设计专著,现任360奇舞团Web前端开发资深专 阅读全文
posted @ 2019-12-05 11:00 demoblog 阅读(681) 评论(0) 推荐(0) 编辑
摘要: 转载: https://www.jianshu.com/p/cf63a1fabc86 现实开发中,例如‘商品列表页’跳转‘商品详情页’,返回时,不重新加载刷新页面,并且滚动到原来的位置。 1.首先,先了解一下pushState、replaceState。 参数(params)功能说明 state 存 阅读全文
posted @ 2019-12-04 16:27 demoblog 阅读(1248) 评论(0) 推荐(0) 编辑
摘要: 转载于: https://blog.csdn.net/qq_31980421/article/details/79662988 flying-saucer + iText + Freemarker实现pdf的导出, 支持中文、css以及图片 1.解决的问题请看图片 或者是这个问题:https://z 阅读全文
posted @ 2019-11-19 17:48 demoblog 阅读(1135) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示