原文: https://jacobpan3g.github.io/cn/2018/02/07/gain-root-permission-for-mac-app/,有问题欢迎在原文评论区一块儿讨论交流,我会及时回复。git
在MacOS App开发中,有一些操做须要管理员权限,须要弹出认证对话框让用户输入帐号和密码,这个过程就是MacOS App提权的过程,主要有下面几种方式:github
1. AuthorizationExecuteWithPrivileges()
使用这个接口最有表明的库是STPrivilegedTask,这是一个封装得很好得App提权库,接口与NSTask十分像,使用起来十分方便。objective-c
惋惜得是AuthorizationExecuteWithPrivileges()接口在MacOS 10.7开始deprecated,听说在10.12的版本该接口就关闭了。shell
所以,若要兼容10.12之后的MacOS版本,就不得不放弃使用STPrivilegedTask库了。app
2. 使用ServiceManagement.framework注册LaunchdDaemon
这是Apple官方目前推荐的提权方式,官方有一个SMJobBless的Demo,是用来有点复杂,具体请见另外一篇文档"SMJobBless官方Demo笔记"less
该方法有一个几个小缺点:spa
- 弹出认证对话框的提示内容是"须要Install Helper",并且每次打开都是这样的提示,对于小白用户来讲,会不会误导用户App总是在安装什么东西?
- LaunchdDaemon及其配置文件是须要安装到
/Library
下的,当用户把App卸载后会不会存在"残留问题"?
3. 使用AppleScript
do shell script "..." with administrator privileges
省略号部分填入shell脚本,任何可执行文件都须要写全路径,如/bin/ls
。线程
以上是AppleScript脚本,经过这种方式提权有如下有点:code
- 比上述"注册LaunchdDaemon"方法实现起来简单不少
- 同时也不用担忧卸载残留的问题,由于所有东西都在.app里
AppleScript脚本在objective-c中有两种执行方式:接口
- 经过NSTask执行"/usr/bin/osascript -e "do shell ...""
- 经过NSAppleScript执行
方法1有两个缺点:
do shell script
会在全部shell执行完成后再把全部stdout返回,所以当启动的是Daemon进程,就算使用NSTask的fileHandle Notification,也没法把stdout分次读取出来。- 这种方法的认证窗口提示信息是"osascript wants to make changes.",对于小白用户来讲会不会有一种这样的感受"我明明安装的是XXX.app,怎么来了一个osascript让我输入帐号密码?会不会是恶意程序?"
而使用NSAppleScript方法时,认证窗口的提示信息是"APP_NAME wants to make changes.",感受这样的提示更加友好。但也有一些缺点:
- NSAppleScript执行Daemon进程的话会直到Daemon退出才退出,即会一直占用线程。 解法:建议在子线程使用NSAppleScript,以避免UI没法响应
- 也存在stdout只能等待Daemon退出才所有打印的问题
Jacob Pan ( jacobpan3g.github.io/cn )