JSch PAM 身份验证 - "Auth fail" - 凭据正确

JSch PAM authentication - "Auth fail" - credentials are correct

我正在构建一个 SFTP class 负责列出远程目录的文件。我正在使用 JSch 库来这样做。我已经设置了一个用户,我可以手动 SSH 到远程服务器就好了。但是,当 JSch 尝试连接时,它会响应

com.jcraft.jsch.JSchException: Auth fail

有一件事我注意到了;当我手动 SSH 到服务器时,我看到它正在使用 "PAM Authentication." 我错过了什么?

Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
Session session = jSch.getSession(username, destination, port);
session.setPassword(password);
session.setConfig(config);
session.connect();

下面的代码已经过测试并且可以正常工作。试试下面的代码:

 /**
     * Transfer a file to remote destination via JSCH library using sFTP protocol
     * 
     * @param username String remote SFTP server user name.
     * @param password String remote SFTP server user password
     * @param host String remote SFTP server IP address or host name.
     * @param file File to transfer to SFTP Server.
     * @param transferProtocol protocol to transfer a file. {@link FileTransferProtocol}
     * @return boolean true if file is transfered otherwise false.
     * @throws ApplicationException
     */
    public static boolean transferFile(final String username, final String password, final String host,
                                       final File file, final FileTransferProtocol transferProtocol) {
  //      throws ApplicationException {
        // currently can deal with sftp only.
 //       LOGGER.trace("Invoking transferFile...");
        JSch jsch = new JSch();
        try {
            Session session = jsch.getSession(username, host);
 //           LOGGER.debug("Session Host: " + session.getHost());
            session.setPassword(password);
            Properties properties = new Properties();
            properties.put("StrictHostKeyChecking", "no");
            session.setConfig(properties);
 //           LOGGER.debug("Connecting to a session Host Server...");
            session.connect();
 //           LOGGER.debug("session is established with host server.");
 //           Channel channel = session.openChannel(transferProtocol.ftpStringRepresentation());
            Channel channel = session.openChannel("sftp");
 //           LOGGER.debug("Connecting to a sftp Channel...");
            channel.connect();
 //           LOGGER.debug("Connected with sftp Channel.");
            ChannelSftp channelSftp = (ChannelSftp) channel;
            channelSftp.put(new FileInputStream(file), file.getName());
 //           LOGGER.debug("File transfered successfully");
            channelSftp.exit();
 //           LOGGER.debug("sftp channel disconnected.");
            channel.disconnect();
 //           LOGGER.debug("channel disconnected.");
            session.disconnect();
  //          LOGGER.debug("session disconnected.");
            return true;
        } catch (JSchException | FileNotFoundException | SftpException e) {
            e.printStackTrace();
//            LOGGER.error(e.getMessage(), e.getCause());
//            throw new ApplicationException(e.getMessage(), ApplicationSeverity.ERROR, e.getCause(), e);
        }
        return false;
    }

URL: https://github.com/SanjayMadnani/com.sanjay.common.common-utils/blob/master/common-utils/src/main/java/com/sanjay/common/util/FileUtil.java

如果您在服务器端使用 PAM 身份验证,则可能需要在客户端实现键盘交互身份验证。

请参阅 What's the difference between “password” and “keyboard-interactive”? 问题以了解 PAM 和键盘交互式身份验证之间的关系。


有关键盘交互身份验证实施示例,请参阅 official UserAuthKI example

基本上你需要实现 UIKeyboardInteractive interface (together with the UserInfo interface) and associate the implementation with the session using the Session.setUserInfo.

如果身份验证仅提示输入单个“密码”,请使用密码实现 UIKeyboardInteractive.promptKeyboardInteractive method 到 return 单个元素数组。


强制警告:不要使用StrictHostKeyChecking=no盲目接受所有主机密钥。这是一个安全漏洞。您失去了针对 MITM attacks. For the correct (and secure) approach, see:

的保护