前言
Electron
是一款使用 JavaScript
, HTML
和 CSS
等 Web
技术创建原生程序的框架,它内部集成了Chromium
和 Node.js
.
前端工程师通过Electron
相关技术,可以开发基于Windows
、Linux
以及Mac
系统的客户端应用,这些能力拓展了前端所能触摸的边界,释放了更大的想象空间.
如果客户端应用仅仅局限于页面内容的展现和操作,通过web
相关技术就可以实现.但由于Electron
集成了Node.js
,这便使开发的应用具备调用操作系统级别服务的能力.
Electron
调用某些操作系统的服务时,往往会受到系统权限的限制.比如在Linux
系统下开发的程序,调用shell
脚本命令时就需要在执行命令前面加上sudo
,运行后再输入管理员密码,密码验证通过后脚本才能如期执行.
win10
操作系统以及mac
系统对权限同样有着严格的把控.本文接下来将研究一下Electron
应用如何在程序运行期间申请提权以及背后的实现原理.
实践
Electron
应用运行期间想申请更高的执行权限,通过引用githup
上的一个js
库sudo-prompt
就能轻松实现.
sudo-prompt
没有外部的依赖以及原生模块的绑定,是一段完全使用nodejs
编写的脚本.
sudo-prompt
将windows
、Linux
以及Mac
系统不同平台下对权限申请方式做了处理和封装,使Electron
应用能支持多平台下的提权操作.接下来将演示一下sudo-prompt
的使用方式,详情可点击访问 仓库地址.
-
项目根目录下执行
npm install sudo-prompt --save
安装依赖. -
调用方式如下代码(当前最新版本
9.2.1
,如果版本不同请访问仓库地址查阅).
创建一个对象options
,属性名name
(应用名称)可以自定义.但name
只能为字母、数字和空格,最多不能超过70
个字符.
最后使用 sudo.exec('命令',...)
执行命令.sudo.exec
一执行就会弹出申请权限的窗口,用户输完密码进入回调函数,stdout
为执行命令后的输出结果.
const sudo = require('sudo-prompt');
const options = {
name: 'Electron'
};
sudo.exec('echo hello', options,
function(error, stdout, stderr) {
if (error) throw error;
console.log('stdout: ' + stdout);
}
);
Linux
图形界面的执行效果图如下:
原理分析
sudo-prompt
在不同平台下对权限做了不同的处理,接下来以Linux
和Windows
为例,探索一下它背后的实现原理.
Linux
当前Linux
系统有四大图形桌面环境,分别是KDE
、Gnome
、Xfce
、LXDE
.其中KDE
和Gnome
都包含了一系列标准的桌面工具和很多功能强大的应用软件,使用体验逐渐逼近Windows
.Xfce
和LXDE
属于轻量级桌面环境.
这些桌面环境安装好后,一般默认会内置一些提升程序权限的指令,比如KDE
图形界面默认内置/usr/bin/kdesudo
,该路径下的kdesudo
指令运行起来就能提示输入管理员密码,允许授权用户以其他身份执行程序.
同样其他桌面环境也如此,利用这些内置的指令程序就能顺利申请管理员权限运行.
具体做法可以先定义两个路径 const paths = ['/usr/bin/kdesudo', '/usr/bin/pkexec']
,先在系统中去寻找这两个程序,看系统中包含哪一个就调用谁.
如果找到了pkexec
,拼接字符串格式如下:
'"/usr/bin/pkexec" --disable-internal-agent "/bin/bash" -c "echo SUDOPROMPT; echo hello"'
如果是kdesudo
,拼接字符串格式如下:
'"/usr/bin/pkexec" --comment "Electron wants to make changes.Enter your password to allow this." -d -- /bin/bash -c "echo SUDOPROMPT; echo hello"'
字符串拼接好后,我们就可以利用Node.js
的子进程Process.child.exec
来执行上面的字符串命令.
如果执行后发现报错,错误信息为No polkit authentication agent foun
. 那可能是因为Linux
系统内polkit
相关的服务没有安装或没启动起来.比如安装的轻量级桌面xfce4
(Ubuntu
系统)可能会缺少这个模块,可以采用以下两步来解决.
- 安装
polkit
sudo apt-get install policykit-1-gnome
- 启动服务
/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1 &
如果一切顺利,命令执行完后界面就会弹出输入密码框,只有当密码验证正确后才会执行上面拼接字符串的最后面的指令echo hello
,这就是我们自定义希望获取系统权限后要执行的指令.
Windows
Windows
系统下使用传统的CMD
窗口去申请管理员的权限十分繁琐,但所幸有PowerShell
的存在让一切都变的非常简单.
Windows PowerShell
是一种和CMD
类似的命令行外壳程序,它可以使命令行用户和脚本编写者利用.NET Framework
的强大功能完成想要的操作.从Windows 7
开始系统就已经内置了PowerShell
.
有了PowerShell
的加持,我们可以先把想要系统去执行的命令封装成一个command.bat
文件(代码如下).
@echo off
chcp 65001>nul
cd /d '/Users/kay/Desktop/demo/project'
echo hello
@echo off
关闭回显,不显示正在执行的批处理命令及执行的结果等.chcp 65001
将命令行窗口活动代码页设置为utf-8
格式cd
切换到项目目录下echo hello
是最终希望系统执行的命令
以上字符可通过字符串的拼接的方式组合而成,再通过Node.js
的fs.writeFile
将字符串写入到command.bat
文件中储存起来.
脚本文件准备好后,接下来拼接命令字符串如下:
powershell.exe Start-Process -FilePath '/Users/kay/Desktop/demo/project/command.bat' -WindowStyle hidden -Verb runAs
powershell
通过添加参数-Verb runAs
就能为应用程序提权,从而执行command.bat
里面的脚本代码.
字符串拼接好后,Node.js
的子进程Process.child.exec
执行字符串命令从而达到最终的目的.
总结
综上所述,不管是Windows
还是Linux
系统,它们都会内置一些提权的程序.只要找到这些程序的调用方式以及相关参数的含义,就能顺利为Electron
应用申请到管理员权限从而完目标操作.