最近運維同窗爲了提升安全性,用Google Authenticator對服務器加了雙重認證,此後登陸服務器須要先輸入動態密碼,在輸入服務器密碼。Google Authenticator至關於軟token,對他不瞭解的同窗能夠看下這篇文章:谷歌驗證 (Google Authenticator) 的實現原理是什麼?。git
運維同窗的出發點是好的,可是我原來寫的各類自動登陸服務器的腳本通通失效了。蛋疼的是我如今登陸服務器的流程變成了:github
本來我只執行本身搞的一個命令就完事了,因爲我常常須要登陸各類不一樣的服務器,這種方式對工做效率的影響是可想而知的。算法
目前Google官方的客戶端只有Android和iOS的,因而開始找找看有沒有針對PC,發現有個針對Windows系統的WinAuth支持Google Authenticator,我不管工做、在家基本都用Mac,因此這個WinAuth我是無法用了,後來在GitHub上找到一個MacAuthenticator的工具,下載下來試用了一下基本能用,至少Mac端能夠獲得Verification Code不須要依賴手機了,可是依然解決不了效率問題,並且那個工具竟然無法退出...shell
沒個順手的工具,看來還得我親手開發個了,因而簡單了設計了下我須要的功能:swift
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平臺上開發過很多桌面類的應用,這塊邊學邊作感受問題不大(實際作的時候發現各類踩坑),在網上找了些快速入門的資料,發現一個很是棒的資料推薦一下:WeatherBarcurl
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吧。
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,致使效率變差的問題得以完美解決,我原來的自動化腳本也能正常使用了,這個項目算是告一段了。回過神,該繼續研究大數據的東西去了 )逃...