极客⼿中的利器Electron
作为⼀个前端开发⼈员,你可能已经听说过 Electron 了,你知道 VS Code 是基于这个技术开发的。不但 VS Code,⽬前⼀些⼤热的软件:飞书、Slack、WhatsApp 都是基于这个技术开发的。即使如此,这也并不⾜以引起你的重视,毕竟桌⾯软件式微,移动端和 Web 开发才是⼤⽅向,你的⼯作可能根本就不会涉及桌⾯开发领域的内容。但我想告诉你的是:
即使⼯作不会涉及到,也应该学⼀下 Electron,因为它是极客⼿⾥的利器,你可以通过他做很多 Amazing 的事情。
本⽂主要讲讲 Electron 是什么,以及它能做什么极客⼯作。
1
Electron 的由来
2011 年左右,中国英特尔开源技术中⼼的王⽂睿(Roger Wang)希望能⽤ Node.js 来操作 WebKit,⽽创建了 node-webkit 项⽬,这就是 NW.js 的前⾝。当时的⽬的并不是⽤这两个技术来开发桌⾯ GUI 应⽤。
中国英特尔开源技术中⼼⼤⼒⽀持了这个项⽬,不但允许王⽂睿分出⼀部分精⼒来做这个开源项⽬,还给了他招聘名额,允许他招聘其他⼯程师来⼀起完成这个项⽬。2012 年,故事的另⼀个主⾓赵成(Cheng Zhao)加⼊到王⽂睿的⼩组,并对 node-webkit 项⽬做出了⼤量的改进。
后来赵成离开了中国英特尔开源技术中⼼,帮助 github 团队尝试把 node-webkit 应⽤到 Atom 编辑器上,但由于当时 node-webkit 还并不稳定,且 node-webkit 项⽬的⾛向也不受赵成的控制,这个尝试最终以失败告终。
但赵成和 github 团队并没有放弃,⽽是着⼿开发另⼀个类似 node-webkit 的项⽬:Atom Shell,这个项⽬就是 Electron 的前⾝,赵成在这个项⽬上倾注了⼤量的⼼⾎,这也是这个项⽬后来⼴受欢迎的关键因素之⼀,再后来 github 把这个项⽬开源出来,最终更名为Electron。
你可能从没听说过这两个名字,但开源界就是有这么⼀批“英雄”,他们不为名利⽽来,⽢做软件⾏业发展的铺路⽯,值得这个领域的所有从业者尊敬(以上内容与 Electron 的作者确认过)。
2
注⼊脚本
Electron 内部拥有⼀个完整得浏览器核⼼,你可以⽤程序操纵这个浏览器核⼼,让它加载⼀个第三⽅
⽹页,⽐如:淘宝的⽣意参谋、⽹易云⾳乐、gitee 等,但单单加载这些⽹页,并没有什么稀奇的,毕竟在浏览器⾥也能加载这些⽹页。最有意思的是,你还可以给这些⽹页注⼊脚本,⽐如像下⾯这样,注⼊⼀个 Js ⽂件到⽬标⽹页:
如果你只希望注⼊⼀两句代码,也可以通过如下形式注⼊脚本:
这些脚本是在⽬标⽹页的作⽤域下执⾏的,与⽬标⽹页的⼯程师⾃⼰写的代码没什么区别。想象⼀下,你如果想调⽤⽬标⽹页的某个服务端接⼝,你是不是应该考虑如何模拟 token,如何跨域等等问题,现在你只需要在脚本⾥直接写调⽤接⼝的逻辑就可以了。
另外,如果你不喜欢⽬标⽹页的页⾯样式,你也可以直接注⼊⼀段样式脚本,代码如下:
值得⼀提的是,你注⼊的脚本还可以访问 Node.js 的 API。也就是说,你在脚本中获取到了⽬标⽹页的资源后,可以直接写到你本地⽂件⾥。
3js脚本编程入门
突破同源策略的限制
注⼊了脚本,获取到了受限的资源,你可能希望把这些资源提交到你⾃⼰的服务器上,或者你可能希望在注⼊的脚本⾥,访问另⼀个⽹站的API,以获取更多的资源,这个时候,如果没做特殊配置的话,同源策略就会起作⽤,限制你这么⼲,浏览器往往会报如下错误:
“同源策略”是浏览器的⼀个安全功能,“同源”是指如果两个页⾯的协议(http/https)、端⼝和主机都相同,则两个页⾯具有相同的源。同源策略规定不同源的客户端脚本在没有明确授权的情况下,不能读写对⽅资源。只有同⼀个源的脚本才具备读写 cookie、session、ajax 等的操作的权限。
在 Electron 中突破同源策略,就是⼀两个配置的事情,代码如下:
这样设置之后,浏览器的所有同源策略限制就全部失效了。如果你只是希望在 https 域下访问 http 的资源,那么你可以不⽤关掉整个同源策略,只需要把 allowRunningInsecureContent 这个配置设置为 true 即可(它同样也是 webPreferences 下的⼀个属性)。如果你设置 webSecurity 为 false 了,那么 allowRunningInsecureContent 会⾃动设置为 true。
4
读写受限访问的 Cookie
由于浏览器每次与服务端的交互,都会携带同域下的所有 Cookie,所以⽹站开发者往往会把标记⽤户⾝份的信息(⽐如⽤户 token)放到Cookie ⾥。
⼀般情况下,前端开发⼯程师可以使⽤ kie 访问浏览器⾥存储的同域的 Cookie,但也有例外,凡标记了 HttpOnly 的Cookie,通过这种⽅式都是访问不到的。⽹站开发者之所以这么做,主要是为了防⽌跨站脚本攻击(XSS)和跨站请求攻击(CSRF)。
跨站脚本攻击(XSS,是 Cross Site Scripting 的缩写),⼀旦⽹站允许⽤户提交内容,并且会在⽹站的某些页⾯上显⽰⽤户提交的内容,⽐如留⾔或者博客,那么不做防范的话,就有可能受到跨站脚本攻击。恶意⽤户会在提交内容时在内容中夹带⼀些恶意 JavaScript 脚本,当其他⽤户访问页⾯时,浏览器会运⾏这些恶意脚本,恶意脚本有可能会窃取⽤户的 Cookie、页⾯上的⽤户隐私信息等,并发送到恶意⽤户的服务器。他们可以通过这些窃取来的信息模拟⽤户⾝份完成⾮法操作。这就是跨站脚本攻击。
跨站请求攻击(CSRF,是 Cross Site Request Forgery 的缩写),当⽤户登录了⾃⼰信赖的⽹站后,⽤户⾝份信息(token)会被保存保存在⽤户的浏览器上,后来⽤户⼜不⼩⼼打开了⼀个恶意⽹站,这个恶意⽹站可能会要求浏览器请求⽤户信赖的⽹站(通过 iframe 等形式),如果⽤户信赖的⽹站没有
做安全防范的话,可能会被恶意⽹站获取到⽤户的敏感信息(token),从⽽给⽤户带来伤害。
但这个限制在 Electron ⾯前也不值⼀提,我们可以通过下⾯这种⽅式读写受限访问的 Cookie:
通过这种⽅式,⽆论 Cookie 有没有设置 HttpOnly 属性,都可以成功读写。
5
转发/修改请求
有的时候你不单单是希望给第三⽅⽹页附加代码逻辑,⽽是希望侵⼊式的修改第三⽅⽹站⾃⾝的代码逻辑。但往往第三⽅的 JavaScript 代码是在⼀个闭包作⽤域内执⾏的,你的代码没办法注⼊到这个作⽤域内,去访问作⽤域内的变量或⽅法,碰到这样的状况该怎么办呢?
此时,你第⼀步要做的,就是分析清楚它的脚本是如何执⾏的,是哪个脚本⽂件执⾏的。这个过程是⼀个⾮常有趣的过程,不可避免的你要⽤到⾕歌浏览器的开发者调试⼯具,如果对⽅的代码是压缩过的,你可能还要给它“美化”⼀下,再逐步调试。
搞清楚逻辑之后,就把他的脚本⽂件下载下来,然后在这个⽂件中加上你的逻辑,你的逻辑可能就是粗暴的把它闭包作⽤域内的变量暴露到window 对象上。这样你注⼊的脚本,就可以访问这个变量了。
修改完这个脚本⽂件后,把这个脚本⽂件 host 到你⾃⼰的⼀个服务器上,然后通过 Electron 把⽹页加载这个脚本⽂件的请求,转发到你⾃⼰的服务器上去,这个转发请求的代码如下:
当这个⽹页再试图加载这个脚本时,得到的结果将是你修改过的脚本。
有些⽹站对⼀些敏感数据保护的很好,客户端请求这些数据时,得到的是服务端加密过的数据,客户端执⾏解密后,再使⽤这些数据。对于这类⽹站,Electron 的这个能⼒⽆疑是⾮常有⼒的。
当然,你也可以考虑使⽤ PWA 技术⾥的 service worker 来办这个事⼉,甚⾄可以⾃⼰在客户端模拟⼀个响应,不⽤再经由你的服务器转发了。如果你没有⾃⼰的服务器,也可以通过 Node.js 的能⼒,⾃⼰在软件⾥起⼀个 localhost 的服务。所有这些骚操作,都必须时在Electron 内执⾏的哦。
6
反“防盗链”
有的时候你可能只是想把⽬标⽹站的⼀些静态资源嵌⼊到你的应⽤程序中,⽐如:图⽚或者视频。然⽽如果⽬标⽹站已经做了防盗链的⼯作,你这个功能可能就没那么容易实现了。
防盗链的主要⽬的有两个:⼀个是版权问题,别⼈未经授权就使⽤你的资源,另⼀个是流量压⼒的问题,盗链产⽣了⼤量的请求,这些请求对于⽹站运营者来说没任何价值。
防盗链最常见的做法就是识别 HTTP 的 Refer 请求头,这个请求头代表着发起请求时前⼀个⽹页的地
址,⽹站运维⼯程师会根据这个Refer 请求头来推测出当前请求是否为⼀个盗链请求(判断这个 Refer 请求头的内容是不是⾃⼰域名下的⼀个地址)。
Electron 允许开发者监听发起请求的事件,并允许开发者在发起请求前修改请求头,我们可以在这个事件⾥修改这个 Refer 请求头,代码如下:
7
给应⽤植⼊ socks5 代理
Chrome 本⾝是⽀持代理的,使⽤ Electron 你可以通过编程的⽅式把你的代理内置到你的应⽤程序中,这样你的⽤户就可以⾃由的访问国外的⼀些⽹站了:
常见的代理服务器有 http 代理、https 代理和 socks 代理,socks 代理隐蔽性更强,效率更⾼,速度更快。咱们这⾥就聊聊如何在Electron 应⽤内植⼊ socks5 代理访问⽹络服务。
上⾯代码中,我们使⽤ session 实例的 setProxy ⽅法来为当前页⾯设置代理,socks 代理,代理设置成功后,我们马上使⽹页加载了⼀个 IP 地址查询的⽹址,在此页⾯上我们可以看到访问该页⾯的实际 IP 地址,如果这⾥显⽰的地址是你的代理服务器的所在地的地址,那么说明代理设置成功。
以上这种⽅法可以给单个渲染进程设置代理,如果你需要给整个应⽤程序设置代理,可以使⽤如下代码完成:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论