如何在命令行应用程序中创建安全密码输入字段?

时间:2015-02-19 00:15:40

标签: objective-c macos swift

我正在为Swift中的OS X编写命令行应用程序。我需要提示输入用户名和密码(不是用户在计算机上的帐户而不是保存在钥匙串中的凭据)。我可以提示用户名就好了:

func getInput() -> String {
    var keyboard = NSFileHandle.fileHandleWithStandardInput()
    var inputData = keyboard.availableData
    return NSString(data: inputData, encoding:NSUTF8StringEncoding)!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}

let username = getInput()

我也想提示输入密码,但是当用户输入密码时,它会在控制台中输出密码。如何在不将其回送到控制台的情况下接受来自STDIN的输入?

请注意,我需要应用程序是交互式的,用户永远不会将用户名和密码作为命令行参数传递,因此argv不是正确的答案。

例如,在Ruby中执行此操作时,请输入:

require 'io/console'
puts "Enter your password"
@password = STDIN.noecho(&:gets).chomp

然后它将在屏幕上显示为此图像:

Hidden password field example

无论输入多少个字母,它都只显示带有圆点的蓝色框。它不会将密码打印到屏幕上,也不会显示*********作为密码。

是否可以在命令行OS X应用程序中使用Swift或Objective-C执行相同的操作?

3 个答案:

答案 0 :(得分:10)

仅仅为了完整性:getpass()适用于密码,但不幸的是,此功能还有一个限制,即它最多只能读取128个字符。如果您想提示真正长密码或私钥,请使用BSD的readpassphrase()代替。

Swift 2.0示例:

var buf = [Int8](count: 8192, repeatedValue: 0)
let passphrase = readpassphrase("Enter passphrase: ", &buf, buf.count, 0)
if let passphraseStr = String.fromCString(passphrase) {
    print(passphraseStr)
}

Swift 3.1及更高版本:

var buf = [CChar](repeating: 0, count: 8192)
if let passphrase = readpassphrase("Enter passphrase: ", &buf, buf.count, 0),
    let passphraseStr = String(validatingUTF8: passphrase) {

    print(passphraseStr)
}

答案 1 :(得分:7)

inputString = String(validatingUTF8: UnsafePointer<CChar>(getpass("Please enter your password: ")))

这是使用swift

获取输入的方法

答案 2 :(得分:3)

使用C函数getpass(3)。例如:

char *p = getpass("Please enter your password: ");
NSString *password = [NSString stringWithUTF8String:p];
NSLog(@"%@", password);