问题描述
我想在 Java 应用程序中使用 checkpassword-pam。这是一个非常简单的可执行文件,它从 fd 3 读取用户名和密码,然后对其进行验证。 协议描述为here。
在 shell 中,你会像这样使用它:
# echo -e "username\0password\0timestamp\0" \
| checkpassword-pam -s SERVICE \
--debug --stdout -- /usr/bin/id 3<&0
我将如何从 Java 应用程序执行此操作? 我确定它不能通过标准 Java 来完成,但也许可以通过 jna 访问 posix api...
解决方法
回答我自己的问题:一个简单的 shell 命令可以将 fd 3 重定向到 stdin。
try {
Process p = new ProcessBuilder("/bin/sh","-c","exec /usr/bin/checkpassword-pam -s sshd 3<&0 /usr/bin/id").redirectErrorStream(true).start();
OutputStream os = p.getOutputStream();
os.write(userName.getBytes(Charset.defaultCharset()));
os.write(0);
os.write(password.getBytes(Charset.defaultCharset()));
os.write(0);
os.close();
p.waitFor(10,TimeUnit.SECONDS);
if (p.exitValue() == 0) {
logger.info("authenticated user {}",IOUtils.read(p.getInputStream()).trim());
result = true;
} else {
logger.info("authenticated failed for user {}",userName);
result = false;
}
} catch (IOException | InterruptedException e) {
logger.error("failed to authenticate user {}",userName,e);
result = false;
}
,
为了执行您想要的操作,您可以使用 Runtime 类、使用 Runtime.getRuntime()
和运行时的 exec
方法从 Java 程序内部运行命令。由此,您可以使用 Process 类来控制该 shell 命令的标准输入和输出,实质上模拟用户从其控制台键入命令。您可以向here寻求更多帮助