1. 什么是SFTP
SFTP是一个安全文件传送协议,可以为传输文件提供一种安全的加密方法。SFTP 为 SSH的一部份,是一种传输文件到服务器的安全方式。SFTP是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。
2.java项目中使用JSch
Jsch是一个纯粹的用java实现SSH功能的java library,支持密码登录方式和秘钥登录方式。用密码登录,就是和我们用ftp的账号密码登录一样,比较简单。秘钥登录方式,就需要把客户端的公钥放到SFTP服务器,然后客户端需要用秘钥登录。
3.Jsch文件上传示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
| import com.jcraft.jsch.*; import lombok.Data; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import java.io.IOException; import java.io.InputStream; import java.util.Properties;
@Data @Configuration @Component public class SFtpUtils { private static Logger log = LoggerFactory.getLogger(SFtpUtils.class);
public static boolean uploadFile(String ftpAddress, int ftpPort, String ftpUserName, String ftpPassowrd, String privateKeyFile, String ftpFileName, String ftpPath, InputStream localFile) throws JSchException { boolean success = false; ChannelSftp channelSftp = null; Session jschSession = null; try { JSch jsch = new JSch(); if (StringUtils.isNotEmpty(privateKeyFile)) { jsch.addIdentity(privateKeyFile); } jschSession = jsch.getSession(ftpUserName, ftpAddress, ftpPort); if (StringUtils.isNotEmpty(privateKeyFile)) { jschSession.setUserInfo(new SftpAuthKeyUserInfo(privateKeyFile)); } else if (StringUtils.isNotEmpty(ftpPassowrd)) { jschSession.setPassword(ftpPassowrd); } Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); jschSession.setConfig(sshConfig); jschSession.connect(); channelSftp = (ChannelSftp) jschSession.openChannel("sftp"); channelSftp.connect(); String[] paths = ftpPath.split("/"); StringBuffer sb = new StringBuffer(); for (String p : paths) { if (StringUtils.isEmpty(p)) { continue; } sb = sb.append("/" + p); try { channelSftp.cd(sb.toString()); } catch (SftpException ex) { channelSftp.mkdir(sb.toString()); channelSftp.cd(sb.toString()); } } channelSftp.put(localFile, ftpFileName); channelSftp.exit(); success = true; } catch (SftpException e) { e.printStackTrace(); log.error("IOException", e); } finally { if (channelSftp != null) { channelSftp.disconnect(); } if (jschSession != null) { jschSession.disconnect(); } if (localFile != null) { try { localFile.close(); } catch (IOException e) { e.printStackTrace(); } } } return success; }
public static ChannelSftp getChannelSftp(String ftpAddress, int ftpPort, String ftpUserName, String ftpPassowrd) { ChannelSftp channelSftp = null; Session jschSession = null; try { JSch jsch = new JSch(); jschSession = jsch.getSession(ftpUserName, ftpAddress, ftpPort); jschSession.setPassword(ftpPassowrd); Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); jschSession.setConfig(sshConfig); jschSession.connect(); channelSftp = (ChannelSftp) jschSession.openChannel("sftp"); channelSftp.connect(); return channelSftp; } catch (JSchException e) { e.printStackTrace(); log.error("IOException", e); if (channelSftp != null) { channelSftp.disconnect(); } if (jschSession != null) { jschSession.disconnect(); } } finally { } return null; } public static void close(ChannelSftp channelSftp) { if (channelSftp != null) { channelSftp.disconnect(); } }
static class SftpAuthKeyUserInfo implements UserInfo{
private String passphrase;
public SftpAuthKeyUserInfo (String passphrase) { this.passphrase = passphrase; } @Override public String getPassphrase() { return passphrase; } @Override public String getPassword() { return null; } @Override public boolean promptPassword(String message) { return false; } @Override public boolean promptPassphrase(String message) { return true; } @Override public boolean promptYesNo(String message) { return true; } @Override public void showMessage(String message) { log.info ("SSH Message:{}", message); } } }
|
4.秘钥登录方式怎么传文件的路径呢?
我在项目中是把秘钥文件放在了resource资源目录下。然后根据项目环境取不同环境的秘钥。

1
| ClassPathResource classPathResource = new ClassPathResource(privateKeyPathEnv + "/id_rsa");String sftpPrivatePath = classPathResource.getFile().getAbsolutePath();
|