本文介紹在Java中如何使用基于SSH的文件傳輸協(xié)議(SFTP)將文件從本地上傳到遠(yuǎn)程服務(wù)器,或者將文件在兩個服務(wù)器之間安全的傳輸。我們先來了解一下這幾個協(xié)議
- SSH 是較可靠龙考,專為遠(yuǎn)程登錄會話和其他網(wǎng)絡(luò)服務(wù)提供安全性的協(xié)議箱硕。比如:我們購買的云服務(wù)器登陸的時候使用的協(xié)議都是ssh儿倒。
- ftp協(xié)議通常是用來在兩個服務(wù)器之間傳輸文件的版保,但是它本質(zhì)上是不安全的呜笑。
- 那么SFTP是什么夫否?SFTP可以理解為SSH + FTP彻犁,也就是安全的網(wǎng)絡(luò)文件傳輸協(xié)議。
一般來說凰慈,SFTP和FTP服務(wù)都是使用相應(yīng)的客戶端軟件來提供服務(wù)汞幢。如果你希望在java代碼中使用SFTP協(xié)議進(jìn)行安全的文件傳輸,那么這篇文章非常適合你微谓。
1. 導(dǎo)入JSch 依賴包
在maven項目pom.xml中導(dǎo)入如下的坐標(biāo)森篷,我們使用JSch,JSch將SFTP協(xié)議封裝為對應(yīng)的API供我們調(diào)用豺型。
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
2. 文件傳輸 – JSch例子
2.1 get與put方法
在中JSch
仲智,我們可以使用put
和get
在服務(wù)器之間進(jìn)行文件傳輸。put
方法用來將文件從本地系統(tǒng)傳輸?shù)竭h(yuǎn)程服務(wù)器姻氨。
channelSftp.put(localFile, remoteFile);
get
方法將文件從遠(yuǎn)程服務(wù)器下載到本地系統(tǒng)钓辆。
channelSftp.get(remoteFile, localFile);
2.2 使用用戶名和密碼進(jìn)行認(rèn)證
JSch jsch = new JSch();
jsch.setKnownHosts("/home/zimug/.ssh/known_hosts");
jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);
jschSession.setPassword(PASSWORD);
- "/home/zimug/.ssh/known_hosts"為SSH的known_hosts文件,也就是可信遠(yuǎn)程主機的公鑰保存文件肴焊。
- USERNAME 為用戶名
- REMOTE_HOST遠(yuǎn)程主機的Ip
- REMOTE_PORT遠(yuǎn)程主機端口
- PASSWORD遠(yuǎn)程主機登錄密碼
2.3.使用公鑰和私鑰進(jìn)行認(rèn)證
如果讀者不能理解公鑰和私鑰的用法及含義前联,需要先自行補充一下SSH知識。
- 本地私鑰–
/home/登錄用戶名/.ssh/id_rsa
- 遠(yuǎn)程公鑰默認(rèn)保存位置–
~/.ssh/authorized_keys
JSch jsch = new JSch();
jsch.setKnownHosts("/home/zimug/.ssh/known_hosts");
jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);
jsch.addIdentity("/home/zimug/.ssh/id_rsa");
2.4 完整JSch
文件傳輸示例
將文件從本地系統(tǒng)傳輸?shù)竭h(yuǎn)程服務(wù)器1.2.3.4
娶眷,并使用SSH密碼登陸方式進(jìn)行身份驗證似嗤。
import com.jcraft.jsch.*;
public class SFTPFileTransfer {
private static final String REMOTE_HOST = "1.2.3.4"; //遠(yuǎn)程主機ip
private static final String USERNAME = ""; //登錄用戶名
private static final String PASSWORD = ""; //登陸密碼
private static final int REMOTE_PORT = 22; //ssh協(xié)議默認(rèn)端口
private static final int SESSION_TIMEOUT = 10000; //session超時時間
private static final int CHANNEL_TIMEOUT = 5000; //管道流超時時間
public static void main(String[] args) {
String localFile = "/home/zimug/local/random.txt"; //本地文件路徑
String remoteFile = "/home/zimug/remote/targetfile.txt"; //上傳到遠(yuǎn)程的文件路徑,要保證登錄用戶有寫權(quán)限
Session jschSession = null;
try {
JSch jsch = new JSch();
jsch.setKnownHosts("/home/zimug/.ssh/known_hosts");
jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);
// 通過ssh私鑰的方式登錄認(rèn)證
// jsch.addIdentity("/home/zimug/.ssh/id_rsa");
// 通過密碼的方式登錄認(rèn)證
jschSession.setPassword(PASSWORD);
jschSession.connect(SESSION_TIMEOUT);
Channel sftp = jschSession.openChannel("sftp"); //建立sftp文件傳輸管道
sftp.connect(CHANNEL_TIMEOUT);
ChannelSftp channelSftp = (ChannelSftp) sftp;
// 傳輸本地文件到遠(yuǎn)程主機
channelSftp.put(localFile, remoteFile);
channelSftp.exit();
} catch (JSchException | SftpException e) {
e.printStackTrace();
} finally {
if (jschSession != null) {
jschSession.disconnect();
}
}
System.out.println("文件傳輸完成届宠!");
}
}
3. JSch異常處理
在文件上傳的過程中烁落,我們可能會遇到下面的一些異常
3.1UnknownHostKey異常
需要將遠(yuǎn)程服務(wù)器IP地址添加到known_hosts
文件中。
$ ssh-keyscan -t rsa 1.2.3.4 >> ~/.ssh/known_hosts
3.2對于私鑰無效異常
有可能是遠(yuǎn)程服務(wù)器重新生成了私鑰豌注,需要把私鑰分發(fā)復(fù)制到本地服務(wù)器伤塌。
ssh-copy-id -i ~/.ssh/id_rsa.pub <被分發(fā)的服務(wù)器ip>
3.3對于Auth fail
異常
請確保提供的登錄密碼時正確的
com.jcraft.jsch.JSchException: Auth fail
at com.jcraft.jsch.Session.connect(Session.java:519)
at com.zimug.io.howto.SFTPFileTransfer.main(SFTPFileTransfer.java:34)
歡迎關(guān)注我的博客,里面有很多精品合集
- 本文轉(zhuǎn)載注明出處(必須帶連接幌羞,不能只轉(zhuǎn)文字):字母哥博客寸谜。
覺得對您有幫助的話,幫我點贊属桦、分享熊痴!您的支持是我不竭的創(chuàng)作動力! 聂宾。另外果善,筆者最近一段時間輸出了如下的精品內(nèi)容,期待您的關(guān)注系谐。