SFTP是一个安全文件传送协议,可以为传输文件提供一种安全的加密方法。SFTP 为 SSH的一部份,是一种传输文件到服务器的安全方式。SFTP是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。
Jsch是一个纯粹的用java实现SSH功能的java library。如果要知道Jsch的功能需先了解一下SSH。SSH是一个安全协议,用来在不同系统或者服务器之间进行安全连接,在连接和传送数据的过程中会进行加密。SSH一般是基于客户端的或者Linux命令行,比如window同过OpenSSH、putty等客户端的工具,在linux上可以通过ssh username@host命令进行连接。但是如果在Java中如何实现SSH呢?这时候便是通过JSCH来实现此的功能。
SSH 免密登录可以让用户在不输入密码的情况下登录远程服务器,提高登录效率和安全性
步骤:
在本机中生成秘钥,SSH有专门创建SSH密钥的工具ssh-keygen 🚩
- 生成旧版密钥的命令:ssh-keygen -m PEM -t rsa - 生成新版密钥命令:ssh-keygen -t rsa id_rsa:私钥 id_rsa.pub:公钥 给目标服务器添加公钥
ssh-copy-id 用户名@主机
公钥将被复制到目标服务器的~/.ssh/authorized_keys文件中。
ssh-copy-id -p 19222 lihw@10.1.61.118 或
将公钥ftp到目标服务器的.ssh后,cd ~/.ssh,手动将公钥导入到authorized_keys信任列表:
cat 公钥 >> authorized_keys 更新权限公钥权限
# 自此SSH免密登录配置完成。 chmod 644 authorized_keys 配置服务器
在目标服务器上使用文本编辑器打开SSH服务器的配置文件(通常为/etc/ssh/sshd_config):
sudo nano /etc/ssh/sshd_config 确保以下配置选项的值为"yes",如果不是,请进行相应修改:
RSAAuthentication yes PubkeyAuthentication yes 保存修改并关闭配置文件。
重新启动SSH服务器以应用更改:
sudo service ssh restart 测试使用密钥登录
ssh -p 19222 lihw@10.1.61.118 Jsch提供了四种认证机制:
其中publickey方式通过配置公私钥实现SSH免密登录,这里也只是简单讲一下它的使用。
SSH公钥检查机制:
公钥检查机制是一个安全机制,可以防范中间人劫持等黑客攻击。SSH连接远程主机时,会检查主机的公钥。如果是第一次该主机,会显示该主机的公钥摘要,提示用户是否信任该主机。当选择接受,就会将该主机的公钥追加到文件 ~/.ssh/known_hosts 中。当再次连接该主机时,就不会再提示该问题了。 但是在某些特殊的情况下,严格的SSH公钥检查可能会破坏一些依赖SSH协议的自动化任务如Java的Jsch免密登录sftp程序。解决方式为调整StrictHostKeyChecking配置指令。StrictHostKeyChecking选项如下3种:
session.setConfig("StrictHostKeyChecking", "no/ask/yes👇"); 下面根据password来分析publickey方式与其区别:
设置配置类对象
SftpAuthKeyUserInfo.java
import com.jcraft.jsch.UserInfo; import lombok.extern.slf4j.Slf4j; /** * ssh private key passphrase info */ @Slf4j public class UserInfoImpl implements UserInfo { /** * ssh private key passphrase */ private String passphrase; public UserInfoImpl (String passphrase) { this.passphrase = passphrase; } @Override public String getPassphrase() { return passphrase; } @Override public String getPassword() { return null; } @Override public boolean promptPassphrase(String s) { return true; } @Override public boolean promptPassword(String s) { return false; } @Override public boolean promptYesNo(String s) { return true; } @Override public void showMessage(String message) { log.info ("SSH Message:{}", message); } } try { JSch jsch = new JSch(); session = jsch.getSession(sftpProperties.getUsername(), sftpProperties.getHost(), sftpProperties.getPort()); if (sftpProperties.isCheckToHostKey()) { session.setConfig("PreferredAuthentications", "publickey"); session.setConfig("userauth.gssapi-with-mic", "no"); session.setConfig("StrictHostKeyChecking", "ask"); session.setUserInfo(new SftpAuthKeyUserInfo(sftpProperties.getPassword())); jsch.addIdentity(sftpProperties.getKeyPath()); } else { session.setConfig("PreferredAuthentications", "password"); session.setConfig("StrictHostKeyChecking", "no"); session.setPassword(sftpProperties.getPassword()); } session.setConfig("UseDNS", "no"); session.setConfig("kex", "diffie-hellman-group1-sha1," + "diffie-hellman-group-exchange-sha1," + "diffie-hellman-group-exchange-sha256"); session.connect(sftpProperties.getConnectTimeout()); channelSftp = (ChannelSftp) session.openChannel("sftp"); channelSftp.connect(); originalDir = channelSftp.pwd(); } catch (Exception e) { disconnect(); throw new IllegalStateException("failed to create sftp Client", e); } package io.github.lihewei7.easysftp.config; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.LinkedHashMap; /** * @explain: SFTP client configuration information * @author: lihewei */ @ConfigurationProperties("sftp") public class SftpProperties { private String host = "localhost"; private int port = 22; private String username; private String password = ""; /** * Connection timeout. */ private int connectTimeout = 0; /** * Enable jsch log, Cannot be individually turned on or off for one of multiple hosts. */ private boolean enabledLog = false; /** * Whether to use a key to log in */ private Boolean isCheckToHostKey = false; /** * SSH kex algorithms. */ private String kex; /** * host key. */ private String keyPath; /** * Configuring multiple hosts. */ private LinkedHashMap hosts; public LinkedHashMap getHosts() { return hosts; } public void setHosts(LinkedHashMap hosts) { this.hosts = hosts; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isEnabledLog() { return enabledLog; } public void setEnabledLog(boolean enabledLog) { this.enabledLog = enabledLog; } public int getConnectTimeout() { return connectTimeout; } public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } public Boolean isCheckToHostKey() { return isCheckToHostKey; } public void setCheckToHostKey(Boolean checkToHostKey) { isCheckToHostKey = checkToHostKey; } public String getKex() { return kex; } public void setKex(String kex) { this.kex = kex; } public String getKeyPath() { return keyPath; } public void setKeyPath(String keyPath) { this.keyPath = keyPath; } }