最近运维同学为了提高安全性,用Google Authenticator对服务器加了双重认证,此后登录服务器需要先输入动态密码,在输入服务器密码。Google Authenticator相当于软token,对他不了解的同学可以看下这篇文章:谷歌验证 (Google Authenticator) 的实现原理是什么?。

运维同学的出发点是好的,但是我原来写的各种自动登录服务器的脚本统统失效了。蛋疼的是我现在登录服务器的流程变成了:

  1. 掏手机(我的是iPhone)
  2. 解锁,碰上指纹解锁失败的情况还需要输入密码解锁
  3. 打开Authenticator客户端,等待Verification Code更新大概1s
  4. 记住Verification Code,然后到Mac端输入
  5. 输入服务器密码,登录...

原本我只执行自己搞的一个命令就完事了,由于我经常需要登录各种不同的服务器,这种方式对工作效率的影响是可想而知的。

目前Google官方的客户端只有Android和iOS的,于是开始找找看有没有针对PC,发现有个针对Windows系统的WinAuth支持Google Authenticator,我无论工作、在家基本都用Mac,所以这个WinAuth我是没法用了,后来在GitHub上找到一个MacAuthenticator的工具,下载下来试用了一下基本能用,至少Mac端可以得到Verification Code不需要依赖手机了,但是依然解决不了效率问题,而且那个工具居然没法退出...

没个顺手的工具,看来还得我亲手开发个了,于是简单了设计了下我需要的功能:

  1. 支持从二维码中直接识别Authentication Code,也就是otpauth协议中的那个secret
  2. 支持Authentication Code管理,保存、添加、删除这些基本功能得有
  3. 能够非常方便的得到我想要的Verification Code
  • 不需要手抄验证码,点击自动复制
  • 支持全局快捷键直接填充验证码,不需要麻烦的点鼠标(我工作用触摸板,不用鼠标,比较依赖键盘)
  • 支持在shell脚本中获取验证码(只有这样,才能让我以前写的自动化工具正常工作)

技术调研

GitHub上已经有个MacAuthenticator开源项目了(基于OC的),所以技术实现上应该没什么障碍。

语言方面,因为14年的时候参与过《The Swift Programming Language》翻译(现在已经成为苹果官方指定的中文版本了),但是还从来没用过Swift,所以决定采用Swift开发,就当学习了。

otp协议方面,Google开源了其算法:google-authenticator,刚好也有个iOS版本的,是基于OC的,不过给Swift调用没啥问题,所以核心协议的处理直接拿来用就可以了。

如何将生成的Verification Code给其他应用调用?想来想去还是基于HTTP的调用起来比较简单,所以还需要实现一个内嵌的HTTP服务器,到cocoapods上找了下,发现Swifter比较适合。

macOS上的Application我确实是第一次接触,不过在Windows平台上开发过不少桌面类的应用,这块边学边做感觉问题不大(实际做的时候发现各种踩坑),在网上找了些快速入门的资料,发现一个非常棒的资料推荐一下:WeatherBar

最终成果

GoldenPassport已经放到GitHub上了,项目主页有一个简单的使用说明,我这里就不介绍具体功能了,基本照着我的需求实现的。

几乎所有功能都在这个菜单里搞定了:

从二维码中识别OTP地址,没有二维码,自己手动输入也可以:

和Shell脚本集成,全靠这个HTTP接口啦:

# you can get the url from `http://localhost:17304/`
code=$(curl 'http://localhost:17304/code/test@stanzhai.site')
# ues the verification code
echo $code

技术点

开发过程中,踩了很多坑,遇到不少难点(主要是可参考的资料少),我这里简单的梳理下,对源码感兴趣的同学,直接去GitHub上Fork吧。

基于Google的OTP库生成Verification Code

let data = OTPAuthURL.base32Decode(otpData.secret)
let gen = TOTPGenerator(secret: data,
algorithm: TOTPGenerator.defaultAlgorithm(),
digits: TOTPGenerator.defaultDigits(),
period: TOTPGenerator.defaultPeriod())
let code = gen?.generateOTP(for: Date())  // 这个code就是最终的结果啦

状态栏图标不清晰的问题

如果你的statusIcon是个18*18的png,参照网上的例子去弄的话,你会发现状态栏图标相当模糊,远不如系统自带的清晰,如果你用的png是个比较大的图片,你会发现状态栏中根本显示不下,解决这个问题的关键点是需要指定图片的大小。

statusIcon = NSImage(named: "statusIcon")  // 48 * 48的大小就可以了
statusIcon.size = NSMakeSize(20, 20)  // 这是保证高清又能正常显示的关键

给状态栏按钮绑定事件

获取到系统状态栏按钮对象后,我需要绑定下点击事件,来显示菜单,折腾了许久才搞定,主要卡在action这个地方,网上关于这方面的资料是相当少,在Swift3中,我们创建一个Selector的正确姿势是#selector(方法名)同时必须指定statusItem.target = self才行。

statusItem = NSStatusBar.system().statusItem(withLength: NSSquareStatusItemLength)
statusItem.target = self
statusItem.action = #selector(openMenu)

绑定全局快捷键

这方面的资料真的好少~

let opts = NSDictionary(object: kCFBooleanTrue, forKey: kAXTrustedCheckOptionPrompt.takeUnretainedValue() as NSString) as CFDictionary
guard AXIsProcessTrustedWithOptions(opts) == true else { return }
monitor = NSEvent.addGlobalMonitorForEvents(matching: .keyDown, handler: self.handleKeydownEvent)

窗口默认居中显示

httpPortConfigWindow.showWindow(nil)
httpPortConfigWindow.window?.makeKeyAndOrderFront(nil)
httpPortConfigWindow.window?.center()
NSApp.activate(ignoringOtherApps: true)

不同组件间消息交互

Foundation库为我们提供了一个基于观察者模式的NotificationCenter,用起来相当方便。

// 组件A监听消息
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self,
selector: #selector(verifyCodeAdded),
name: NSNotification.Name(rawValue: "VerifyKeyAdded"),
object: nil)
// 组件B发送消息
let notificationCenter = NotificationCenter.default
notificationCenter.post(name: NSNotification.Name(rawValue: "VerifyKeyAdded"), object: nil)

复制内容到剪贴板

let pasteboard = NSPasteboard.general()
pasteboard.clearContents()
pasteboard.setString(codeInfo.value, forType: NSStringPboardType)

调用系统打开窗口,只允许选择图片类型

let openPanel = NSOpenPanel()
openPanel.allowedFileTypes = NSImage.imageTypes()

从文件中识别二维码

网上大部分都是iOS扫二维码的示例,OSX下从文件中识别的方法,摸索了好一阵子才实现。

let ciImage = CIImage(contentsOf: openPanel.url!)
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyLow])
let results = detector?.features(in: ciImage!)
if (results?.count)! > 0 {
let qrFeature = results?.last as! CIQRCodeFeature
let data = qrFeature.messageString   // 识别后的数据
...
}

收获

GoldenPassport是我开发的第一个macOS Application,对桌面应用的开发流程算是清楚了,搞个窗口类的应用已无大碍。和Windows的桌面应用开发体验相比,感觉OSX的还是差了不少,这也跟自己不熟悉OSX有关吧。

踩了不少Swift语法的坑,现在用的是Swift3,网上找的一些资料不一定是针对Swift3的代码,拿过来不一定用,Swift的这种兼容性问题还是挺让人讨厌的。Swift4也快要出来了,依然有兼容性问题。

由于对Cocoa框架不熟悉,不少NSXXX的API不知道咋用,另外NS的不少API在Swift下用法变掉了,多亏了GitHub,通过GitHub的代码搜索功能,可以找到很多别人项目里的示例代码,在结合Swift的语法,开发过程中碰到的一些功能性问题基本都能解决。

熟悉了Xcode的项目依赖管理工具:cocoapods和Swift Package Manager,对于子子孙孙无穷尽也的项目依赖,熟悉下项目依赖管理工具还是非常有必要的。在GoldenPassport项目因为Swift Package Manager不支持混合语言的项目依赖管理,所以就用了cocoapods来管理项目依赖了。

GoldenPassport的核心功能是我利用周末整整2天多时间折腾出来的,有种参加黑马的感觉,逼着自己做自己不熟悉的东西,现学现做,看看短时间内到底能做成什么样,搞完那一刻成就感满满。

结语

源码地址:GoldenPassport,欢迎Star。

编译好的工具可以到GitHub的releases中下载,如果这个工具能帮助到其他人,那就再好不过了。

引入Google Authenticator,导致效率变差的问题得以完美解决,我原来的自动化脚本也能正常使用了,这个项目算是告一段了。回过神,该继续研究大数据的东西去了 )逃...

为效率而生-开源Mac版Google Authenticator认证客户端GoldenPasspor相关推荐

  1. mac版 google浏览器安装vue-devtools 插件

    1.下载地址 https://gitcode.net/mirrors/vuejs/vue-devtools/-/tree/master 解压得到 2.使用终端进入到文件夹目录内,可以打出cd,然后将文 ...

  2. Mac版Google Chrome快捷键

    标签页和窗口快捷键 操作 快捷键 打开新窗口 ⌘ + n 在无痕模式下打开新窗口 ⌘ + Shift + n 打开新的标签页,并跳转到该标签页 ⌘ + t 重新打开最后关闭的标签页,并跳转到该标签页 ...

  3. inodemac_校园网客户端Mac版-Inode7.0 for mac下载 V7.0-PC6苹果网

    Inode7.0 for mac是 Mac OS平台上一款类似 天翼校园网客户端Mac版 互联网业务接入客户端软件,提供802.1x.Portal等多种认证方式,可以与H3C以太网交换机.路由器等网络 ...

  4. inodemac_Inode Mac版

    今天为您推荐的这款Inode Mac版是天翼校园网客户端Mac版是一款互联网业务接入式的客户端软件.它提供了Portal.802.1x等等多种认证方法.还可以跟以太网进行交换机作业.Inode Mac ...

  5. google authenticator python_谷歌验证器(Google Authenticator)

    双因素身份认证就是经过你所知道再加上你所能拥有的这二个要素组合到一块儿才能发挥做用的身份认证系统.双因素认证是一种采用时间同步技术的系统,采用了基于时间.事件和密钥三变量而产生的一次性密码来代替传统的 ...

  6. 谷歌Google Authenticator实现双因素认证

    参考: https://www.cnblogs.com/hanyifeng/p/kevin4real.html 介绍:什么是双因素认证 双因素身份认证就是通过你所知道再加上你所能拥有的这二个要素组合到 ...

  7. .Net Core使用google authenticator打造用户登录动态口令

    1.google authenticator(谷歌身份验证器) 介绍 谷歌身份验证器,即Google Authenticator(Google身份验证器)v2.33 谷歌推出的一款动态口令工具,解决大 ...

  8. Google authenticator 谷歌身份验证,实现动态口令

    Google authenticator 谷歌身份验证,实现动态口令 google authenticator php 服务端 使用PHP类 require_once '../PHPGangsta/G ...

  9. 使用google authenticator(谷歌身份验证器)打造用户登录动态口令

    google authenticator php 服务端 使用php类 直接下载 https://github.com/PHPGangsta/GoogleAuthenticator/raw/maste ...

  10. mac 版ideal 查找类_4款mac窗口切换工具 提高你的工作效率

    工欲善其事必先利其器,今天小编为大家推荐4款mac窗口切换工具,让你可以快速在在打开的应用程序窗口之间查找和切换,提升你的工作效率! 1.AltTab for Mac(窗口快速切换工具) AltTab ...

最新文章

  1. 密码太多记不住?SSO帮你轻松访问VDI及外部资源
  2. 分站实现php,php城市分站是什么原理
  3. php本地测试还是线上,PHP本地与远程测试(一)
  4. 避免许多if块进行验证检查
  5. Vue「五」—— 动态组件、插槽、自定义指令
  6. 平衡二叉树操作的演示
  7. “我没搞懂元宇宙,但一天能赚9w块”
  8. VScode加文件头的方式
  9. Java实验报告(基础练习、选择循环、数组、字符串及类和对象)
  10. java web后台开发规范01
  11. 学习一下 PDF417 条码
  12. 2018.8.2课堂笔记
  13. bada开发tips
  14. 设计模式(四):模板方法模式、迭代器和组合模式、状态模式
  15. iPhone7 plus分辨率行不行
  16. 基于非结构网格的仿真——太湖之光上的巨大挑战
  17. 制作ubuntu自定义系统镜像
  18. iphone 投屏到android,苹果安卓手机投屏之(二)——音频文件在电视上播放
  19. 微型计算机在工程实践中作用,【电子技术论文】思维教学中数字电子技术的应用(共2702字)...
  20. 在线查看Axure的rp文件用这个免费工具!

热门文章

  1. 求一个n阶矩阵的转置矩阵
  2. html5 表单 重置,css修改input表单默认样式重置与自定义大全
  3. 【Oracle】存储过程 遍历树 举例emp表的树状结构
  4. c语言最大乘积问题,利用C语言来求最大连续子序列乘积的方法
  5. firefox 无法启动
  6. 小程序超过部分隐藏,不起作用
  7. 锂电池常规认证-各国认证大全
  8. 独家丨Web3风向从NFTs吹向DAOs?一季度DAO发展回顾
  9. 用于高频接收器和发射器的锁相环(PLL)——第二部分 与PLL相关的两个关键技术规格
  10. 常见的网站功能需求及解决方案