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, ListlistFileName) { 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 |