1. SFTP란?
SFTP는 Secure File Transfer Protocol의 약자로 기존 FTP에 보안이 강화된 전송 방식을 말합니다.
FTP는 일반적으로 인터넷상에서 파일을 전송할 때 많이 사용되고 있는 프로토콜이나 로그인 정보 및 파일 정보를 암호화하지 않기 때문에 정보 노출의 위험성이 있습니다.
이런 위험을 방지하기 위해서 SFTP는 파일 전송 시 로그인 정보 및 파일 정보를 암호화해서 통신을 합니다.
2. 기본 환경구성
- 라이브러리
jsch-0.1.54.jar
3. SFTP 예시소스
// Server에 접속
private void initChannelSftp()
{
channelSftp = null;
session = null;
try
{
// JSch 객체 생성
JSch jsch = new JSch();
// 세션 객체 생성(사용자이름, 호스트명, 접속포트)
session = jsch.getSession(userName, hostName, Integer.valueOf(hostPort));
session.setPassword(passWord);
// 세션과 관련된 정보를 설정
Properties config = new Properties();
config.put(STRICT_HOST_KEY_CHECKING, STRICT_HOST_KEY_CHECKING_FLAG); // 호스트 정보를 검사하지 않음.
session.setConfig(config);
}
catch(Exception e1)
{
logMessage("원격지(파일서버)연결에 필요한 환경정보 셋팅 중 예외가 발생했습니다.(" + e1.getMessage() + ") >> [Method=initChannelSftp()]"
, "others"
, "EXCEPTION"
, "EXCEPTION");
}
}
// Server에 업로드 될 파일객체 생성
public synchronized File[] setUploadFiles(String filePath, List listFileName)
{
Collection c = new ArrayList();
File[] uploadFiles = null;
File dir = null;
File[] dirList = null;
try
{
dir = new File(filePath);
dirList = dir.listFiles();
if(dirList != null && dirList.length > 0)
{
for(int i=0; i < dirList.length; i++)
{
if(listFileName != null && listFileName.size() > 0)
{
for(int j=0; j < listFileName.size(); j++)
{
if(listFileName.get(j) != null && !listFileName.get(j).equals(""))
{
if(dirList[i].getName().equals(listFileName.get(j)))
{
c.add(dirList[i]);
break;
}
}
}
}
}
}
if(!c.isEmpty())
{
uploadFiles = (File[])c.toArray(new File[0]);
}
}
catch(Exception e)
{
logMessage("원격지(파일서버)에 업로드 될 파일객체 셋팅 중 예외가 발생했습니다.(" + e.getMessage() + ") >> [Method=setUploadFiles()]"
, "others"
, "EXCEPTION"
, "EXCEPTION");
}
return uploadFiles;
}
// Server에 파일을 업로드
public synchronized String uploadFileToSFTP(HashMap argsParam, String logDir, String logFileType)
{
String result = "";
int cnt = 0;
initChannelSftp();
File[] file = null;
FileInputStream fis = null;
try
{
SqlSession sess = (SqlSession)argsParam.get("sess");
DatabasesImpl dMod = (DatabasesMod)argsParam.get("dMod");
file = (File[])argsParam.get("uploadFiles");
session = (Session)argsParam.get("session");
channel = (Channel)argsParam.get("channel");
channelSftp = (ChannelSftp)argsParam.get("channelSftp");
HashMap prvMap = new HashMap();
//channelSftp.chmod(0777, destinationDir);
try
{
// 실질적으로 파일이 업로드되는 경로로 바꿔준다.
channelSftp.cd(destinationDir);
}
catch(SftpException e2)
{
logMessage("원격지(파일서버)에 파일이 업로드 될 디렉토리를 찾을 수 없습니다.(" + destinationDir + ") >> [Method=uploadFileToSFTP()]"
, logDir
, "EXCEPTION"
, logFileType);
}
if(file != null && file.length > 0)
{
for(int i=0; i < file.length; i++)
{
try
{
fis = new FileInputStream(file[i].getAbsoluteFile());
channelSftp.put(fis, file[i].getName());
// 원격지 서버에 업로드가 성공된 결과파일 로그 남기기.
logMessage(String.format("sftp://%s%s%s", hostName, destinationDir+"/", file[i].getName())
, logDir
, "SUCCESS"
, logFileType);
cnt++;
// 업로드대상 파일마다 하나의 InputStream을 Open하기 때문에 업로드가 완료되면 해당 InputStream객체는 닫아줘야 컨트롤이 가능하다.
fis.close();
fis = null;
}
catch(FileNotFoundException fnfe)
{
logMessage("파일을 찾을 수 없습니다.(" + fnfe.getMessage() + ") >> [Method=uploadFileToSFTP()]"
, logDir
, "EXCEPTION"
, logFileType);
if(logFileType.equals("InvoiceBatch"))
{
prvMap.put("invoice", file[i].getName().substring(0, file[i].getName().indexOf(".")));
prvMap.put("ftpFlag", "N");
prvMap.put("errCd", "PROC002");
prvMap.put("errMsg", fnfe.getMessage());
dMod.dataCUD(sess, prvMap, "updateFtpFailInvBatchProcData");
prvMap.clear();
}
result = fnfe.getMessage();
break;
}
catch(SftpException sftpe)
{
logMessage("원격지서버에 파일 업로드 실패했습니다.(" + file[i].getAbsolutePath() + ") >> [Method=uploadFileToSFTP()]"
, logDir
, "FAIL"
, logFileType);
if(logFileType.equals("InvoiceBatch"))
{
prvMap.put("invoice", file[i].getName().substring(0, file[i].getName().indexOf(".")));
prvMap.put("ftpFlag", "N");
prvMap.put("errCd", "PROC002");
prvMap.put("errMsg", sftpe.getMessage());
dMod.dataCUD(sess, prvMap, "updateFtpFailInvBatchProcData");
prvMap.clear();
}
result = sftpe.getMessage();
break;
}
}
}
else
{
logMessage("업로드 대상 파일이 없거나 File객체가 NULL입니다. >> [Method=uploadFileToSFTP()]"
, logDir
, "EXCEPTION"
, logFileType);
result = "fail";
}
if(cnt == file.length)
{
result = "success";
}
else
{
result = "fail";
}
// 연결된 채널, 세션객체를 모두 닫는다.
disconnection(argsParam);
}
catch(Exception e3)
{
logMessage("Session, Channel, ChannelSftp등 연결하지 못했습니다.(" + e3.getMessage() + ") >> [Method=uploadFileToSFTP()]"
, logDir
, "EXCEPTION"
, logFileType);
result = "fail";
}
return result;
}
// Client 단에서 java로 Server에 디렉토리 생성하는 로직
public synchronized HashMap remoteMakeDir(String destinationDir, String logDir, String logFileType)
{
initChannelSftp();
HashMap argsParam = new HashMap();
try
{
// 세션 연결이 되어있지 않다면 세션을 재 연결한다.
if(!session.isConnected()) session.connect();
// sftp 채널을 연다.
channel = session.openChannel(OPEN_CHANNEL_MODE);
channel.connect(); // 채널에 연결한다.
// 채널을 FTP용 채널 객체로 캐스팅한다.
channelSftp = (ChannelSftp) channel;
String[] dirs = destinationDir.split("/");
if(dirs != null && dirs.length > 0)
{
SftpATTRS attrs = null;
int idx = 0;
String pathInfo = "";
for(String folder : dirs)
{
if(idx != 0)
{
if(idx == 1)
{
pathInfo = "/" + folder;
}
else
{
pathInfo = pathInfo + "/" + folder;
}
try
{
attrs = channelSftp.stat(pathInfo);
}
catch(Exception e)
{
//System.out.println("'" + folder + "' not found");
}
if(attrs != null)
{
//System.out.println("Directory exists IsDir=" + attrs.isDir());
}
else
{
channelSftp.mkdir(pathInfo);
channelSftp.cd(pathInfo);
}
}
idx++;
attrs = null;
}
}
// uploadFileToSFTP 메서드에서 사용될 ftp및 session객체 return.
argsParam.put("channelSftp", channelSftp);
argsParam.put("channel", channel);
argsParam.put("session", session);
}
catch(Exception e3)
{
logMessage("Session, Channel, ChannelSftp등 연결하지 못했습니다.(" + e3.getMessage() + ") >> [Method=remoteMakeDir()]"
, logDir
, "EXCEPTION"
, logFileType);
}
return argsParam;
}
// 다이렉트 업로드 로직
public boolean directUpload(
String sftpHost, String sftpUser, String sftpPass,
int sftpPort, String sftpWorkingDir, String fileFullPath) {
boolean result = true;
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
System.out.println("preparing the host information for sftp.");
try {
JSch jsch = new JSch();
session = jsch.getSession(sftpUser, sftpHost, sftpPort);
session.setPassword(sftpPass);
// Host 연결.
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
// sftp 채널 연결.
channel = session.openChannel("sftp");
channel.connect();
// 파일 업로드 처리.
channelSftp = (ChannelSftp) channel;
channelSftp.cd(sftpWorkingDir);
File f = new File(fileFullPath);
String fileName = f.getName();
//fileName = URLEncoder.encode(f.getName(),"UTF-8");
channelSftp.put(new FileInputStream(f), fileName);
f.delete(); // 파일전송 후 Client단 파일 삭제
} catch (Exception ex) {
System.out.println(ex.toString());
System.out.println("Exception found while tranfer the response.");
result = false;
} finally {
// sftp 채널을 닫음.
channelSftp.exit();
// 채널 연결 해제.
channel.disconnect();
// 호스트 세션 종료.
session.disconnect();
}
return result;
}
'IT > Java & Jsp & Spring' 카테고리의 다른 글
| Spring 스케쥴러 사용 (0) | 2019.10.04 |
|---|---|
| Spring Scheduler Lock 설정 in 멀티 클러스터 (0) | 2019.10.04 |
| HTTP와 HTTPS의 차이점 (0) | 2017.12.22 |
| JAVA 개발환경 셋팅하기 with JDK, Eclipse (0) | 2017.11.11 |