본문 바로가기
개발/java

JSch를 사용한 JAVA SFTP 업로드 다운로드 예제 (개인키, 패스워스)

by 가시죠 2021. 8. 18.
반응형

java에서 sftp를 사용하기 위해서는 apache common vfs를 사용하거나, jsch 사용하는 방법이 있다.

jsch 라이브러리를 사용하면 쉽게 개인키나 패스워드를 사용하여 sftp에 접속할 수 있고, 업로드나 다운로드를 할 수 있다.

 

maven repository

https://mvnrepository.com/artifact/com.jcraft/jsch

 

개인키, 공개키 생성

sftp 접속 시 아이디와 패스워드를 사용하지 않고, 아이디와 개인키, 공개키를 사용하면 보안에 좀 더 좋을 수 있다.

(aws의 s3 ftp 사용시에도 키 파일을 이용하여 접속하라고 권고하고 있다.)

 

1. 접속하려는 클라이언트가 되는 서버에서 아래 명령으로 개인키, 공개키를 생성한다.

ssh-keygen -P "" -m PEM -f  원하는키명

(윈도우, 리눅스 동일)

위 명령 실행 시 파일이 2개가 생성되는데, 생성된 키는 아래와 같다.

원하는키명 <- 개인키

원하는키명.pub <- 공개키

 

끝에 .pub가 붙은 파일이 공개키 파일이다.

 

접속하려는 서버 담당자에게 공개키 파일을 전달하고, 개인키는 sftp 접속 시 사용해야 하므로 잘 보관해둔다.

 

JSch 접속 예제 소스

package com.tistory.hitomis.util;

import com.jcraft.jsch.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

public class SFTPUtil {

    private Session session = null;
    private Channel channel = null;
    private ChannelSftp channelSftp = null;

    /**
     * 서버와 연결에 필요한 값들을 가져와 초기화 시킴
     *
     * @param host 서버 주소
     * @param userName 아이디
     * @param password 패스워드
     * @param port 포트번호
     * @param privateKey 개인키
     */
    public void init(String host, String userName, String password, int port, String privateKey) {

        JSch jSch = new JSch();

        try {
            if(privateKey != null) {//개인키가 존재한다면
                jSch.addIdentity(privateKey);
            }
            session = jSch.getSession(userName, host, port);

            if(privateKey == null && password != null) {//개인키가 없다면 패스워드로 접속
                session.setPassword(password);
            }

            // 프로퍼티 설정
            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no"); // 접속 시 hostkeychecking 여부
            session.setConfig(config);
            session.connect();
            //sftp로 접속
            channel = session.openChannel("sftp");
            channel.connect();
        } catch (JSchException e) {
            e.printStackTrace();
        }

        channelSftp = (ChannelSftp) channel;
    }

    /**
     * 디렉토리 생성
     *
     * @param dir 이동할 주소
     * @param mkdirName 생성할 디렉토리명
     */
    public void mkdir(String dir, String mkdirName) {
        if (!this.exists(dir + "/" + mkdirName)) {
            try {
                channelSftp.cd(dir);
                channelSftp.mkdir(mkdirName);
            } catch (SftpException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 디렉토리( or 파일) 존재 여부
     * @param path 디렉토리 (or 파일)
     * @return
     */
    public boolean exists(String path) {
        Vector res = null;
        try {
            res = channelSftp.ls(path);
        } catch (SftpException e) {
            if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
                return false;
            }
        }
        return res != null && !res.isEmpty();
    }

    /**
     * 파일 업로드
     *
     * @param dir 저장할 디렉토리
     * @param file 저장할 파일
     * @return 업로드 여부
     */
    public boolean upload(String dir, File file) {
        boolean isUpload = false;
        SftpATTRS attrs;
        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            channelSftp.cd(dir);
            channelSftp.put(in, file.getName());

            // 업로드했는지 확인
            if (this.exists(dir +"/"+file.getName())) {
                isUpload = true;
            }
        } catch (SftpException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return isUpload;
    }

    /**
     * 파일 다운로드
     *
     * @param dir 다운로드 할 디렉토리
     * @param downloadFileName 다운로드 할 파일
     * @param path 다운로드 후 로컬에 저장될 경로(파일명)
     */
    public void download(String dir, String downloadFileName, String path) {
        InputStream in = null;
        FileOutputStream out = null;
        try {
            channelSftp.cd(dir);
            in = channelSftp.get(downloadFileName);
        } catch (SftpException e) {
            e.printStackTrace();
        }

        try {
            out = new FileOutputStream(new File(path));
            int i;

            while ((i = in.read()) != -1) {
                out.write(i);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 연결 종료
     */
    public void disconnection() {
        channelSftp.quit();
        session.disconnect();
    }
}

 

사용방법 예제 소스

package com.tistory.hitomis;

import com.tistory.hitomis.util.SFTPUtil;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 테스트를 위한 클래스
 */
public class JavaTest {

    public static void main(String[] args) {

        final SFTPUtil sftpUtil = new SFTPUtil();

        final String host = "접속할 서버 아이피";
        final String userName = "접속할 아이디";
        final int port = 22;
        final String uploadPath = "업로드경로";
        final String downloadPath = "다운로드경로";
        final String privateKey = "개인키경로/파일명";
        
        // 업로드 시 업로드 폴더 아래에
        // 현재 날짜 년월일을 생성하고 그 아래 올리기 위한 날짜 변수
        final Date today = new Date();
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

		// 접속
        sftpUtil.init(host, userName, null, port, privateKey);

        // 업로드 테스트
        File uploadfile = new File("업로드할 경로+파일명"); // 파일 객체 생성
       
        String mkdirPath = sdf.format(today); //현재날짜 년월일
        sftpUtil.mkdir(uploadPath, mkdirPath); // 업로드경로에 현재날짜 년월일 폴더 생성
        boolean isUpload = sftpUtil.upload(uploadPath+mkdirPath, uploadfile); //업로드
        System.out.println("isUpload -" + isUpload); // 업로드 여부 확인

        /* 다운로드 테스트 */
        sftpUtil.download(downloadPath, "다운로드파일명", "로컬에저장할경로+파일명");
        File downloadFile = new File("로컬에저장할경로+파일명");
        if (downloadFile.exists()) {
            System.out.println("다운로드 완료");
            System.out.println(downloadFile.getPath());
            System.out.println(downloadFile.getName());
        }

        // 업로드 다운로드 수행 후 꼭 연결을 끊어줘야 한다!!
        sftpUtil.disconnection();
    }
}

 

 

 

 

 

반응형

댓글