ちょっと前に書いたログファイルをダウンロードする機能ですが、実機となるLINUX上にデプロイすると動きませんでした。。。サーバへ接続はできているようなのですが瞬時に切断されているようです。原因切り分けの為、作業中に使っているユーザーIDで試してみると特に問題無く動いてます。TeraTermから指定のIDでログインしてみると即切断されたようになり、WinSCPでSFTPログインすると問題無くアクセスできます。
で、要件を思い出すと、「SFTPはOK」ではなく、「SFTPのみOK」であった事に気が付きました。与えられたユーザーIDでは、SSH接続ができないセキュリティ設定になっていたという事なんです。(sshd_configでSFTP専用にされてました)
要件上はたった2文字の違いですが、実装上は明らかに別物であり、SSHで接続するような実装ではNGという事になります。
となるとGamynedのようにSSHを前提にしたライブラリでなく、SFTPのみでサーバへアクセスできるライブラリを探し、ApacheCommonsのVFSに落ち着きました。なお、VSFにはJschが必要みたいです。
login,logoutはなさそうなんで、ManagedBeanの呼び出しメソッド引数にID、パスワード、ホスト名を追加して、SFTP処理クラスが殆どの変更箇所となります。とりあえず、ファイル受信は出来ましたので別途整理します。
<dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-vfs2</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.53</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> </dependencies>
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
/**
* SFTPファイルアクセスクラス by apache commons vfs
* */
@Stateless
public class SFTPFileAccess {
public SFTPFileAccess(){
}
/**
* リモートホスト上の指定ディレクトリのファイル一覧を取得する
* @param String RemoteDir ディレクトリ名
* @param List<LogFile> セットするファイル一覧
* @param String User ユーザーID
* @param String Password パスワード
* @param String HostName ホスト名
* @throws IOException
* */
public void getSFTPList(String RemoteDir, List<LogFile> FileList, String User, String Password, String HostName) throws IOException {
FileSystemOptions opts = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
FileSystemManager fsManager = VFS.getManager();
String URL = "sftp://"+URLEncoder.encode(User, "UTF-8");
URL = URL +":" + URLEncoder.encode(Password, "UTF-8");
URL = URL +"@" + URLEncoder.encode(HostName, "UTF-8");
URL = URL + RemoteDir;
FileObject localFileObject=fsManager.resolveFile(URL);
//Directoryチェック
if ( !localFileObject.getType().equals(FileType.FOLDER) ){
return;
}
//ファイル存在チェック
if( ! localFileObject.getType().hasChildren() ){
return;
}
FileObject[] children = localFileObject.getChildren();
for (int i = 0; i < children.length; i++) {
if(StringUtils.isEmpty(children[ i ].getName().getBaseName())){
LogFile file = new LogFile();
file.setFileName(children[ i ].getName().getBaseName());
file.setDirectory(RemoteDir);
file.setFileSize(children[ i ].getContent().getSize());
Date tm = new Date(children[ i ].getContent().getLastModifiedTime());
file.setUpDateTime(DateFormatUtils.format(tm, "yyyy/MM/dd HH:mm:ss"));
FileList.add(file);
}
}
}
/**
* SFTPファイル受信
* @param remoteFile 受信元ファイル
* @param stream ストリーム
* @param String User ユーザーID
* @param String Password パスワード
* @param String HostName ホスト名
* */
public void getFile( String remoteFile, OutputStream stream, String User, String Password, String HostName) throws IOException{
FileSystemOptions opts = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
FileSystemManager fsManager = VFS.getManager();
String URL = "sftp://"+URLEncoder.encode(User, "UTF-8");
URL = URL +":" + URLEncoder.encode(Password, "UTF-8");
URL = URL +"@" + URLEncoder.encode(HostName, "UTF-8");
URL = URL + remoteFile;
FileObject localFileObject = fsManager.resolveFile(URL);
if(!localFileObject.exists()){
throw new IOException();
}
InputStream inputStream = localFileObject.getContent().getInputStream();
BufferedOutputStream bos = new BufferedOutputStream(stream);
byte[] buffer = new byte[1024];
int readLength = 0;
while( (readLength = inputStream.read(buffer)) != -1){
bos.write(buffer, 0, readLength);
}
// close
inputStream.close();
bos.close();
}
}
