通过SFtp的方式访问服务器的文件,一定程度上对服务器的安全性而言有比较大的提升。比方说:服务器只开启部分目录下的访问权限,或者只开启读权限等。
引入依赖
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
常见的有两种登录方式:
1. ip账号密码
2.密钥key方式
代码及方法
package com.hf.zuul.zuul.sftps;
import com.jcraft.jsch.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
/**
* @author hanfei
* @Date 2020/8/23
*/
public class SFtpMethod {
private ChannelSftpsftp;
private Sessionsession;
private Stringip;
private int port;
private StringuserName;
private Stringpassword;
private static final StringfolderPath ="/usr/local/20200805";
private static final StringfileName ="check_credit_apply__mcaus_6eqfy";
public SFtpMethod(String ip, int port, String userName, String password) {
this.ip = ip;
this.port = port;
this.userName = userName;
this.password = password;
}
/**
* 连接服务器,账号密码
*/
public void connection(){
JSch jSch =new JSch();
try {
session = jSch.getSession(userName, ip, port);
session.setPassword(password);
Properties properties =new Properties();
properties.put("StrictHostKeyChecking", "no");
session.setConfig(properties);
session.connect();
sftp = (ChannelSftp)session.openChannel("sftp");
sftp.connect();
}catch (JSchException e) {
e.printStackTrace();
}
}
/**
* 连接服务器,密钥方式
* @param passphrase 密钥口令
* @param keyFile 密钥路径
*/
public void connection(String passphrase, String keyFile){
JSch jSch =new JSch();
try {
jSch.addIdentity(keyFile);
UserInfo userInfo =new MyUserInfo(passphrase);
session = jSch.getSession(userName, ip, port);
session.setUserInfo(userInfo);
session.setTimeout(300000);
Properties properties =new Properties();
properties.put("StrictHostKeyChecking", "no");
session.setConfig(properties);
session.connect();
sftp = (ChannelSftp)session.openChannel("sftp");
sftp.connect();
}catch (JSchException e) {
e.printStackTrace();
}
}
/**
* 获取所有文件名
*/
public ListgetAllFileNames(){
connection();
List fileNames =new ArrayList<>();
try {
Vector entries =sftp.ls(folderPath);
for (ChannelSftp.LsEntry entrie :entries) {
String name = entrie.getFilename();
if (!".".equals(name) && !"..".equals(name)) {
fileNames.add(name);
}
}
}catch (SftpException e) {
e.printStackTrace();
}finally {
close();
}
return fileNames;
}
/**
* 获取所有文件名,密钥方式
*/
public ListgetAllFileNames(String passphrase, String keyFile){
connection(passphrase, keyFile);
List fileNames =new ArrayList<>();
try {
Vector entries =sftp.ls(folderPath);
for (ChannelSftp.LsEntry entrie :entries) {
String name = entrie.getFilename();
if (!".".equals(name) && !"..".equals(name)) {
fileNames.add(name);
}
}
}catch (SftpException e) {
e.printStackTrace();
}finally {
close();
}
return fileNames;
}
/**
* 按行读取文件
* @return
*/
public ListreadByLine(){
connection();
List lines =new ArrayList<>();
try {
sftp.cd(folderPath);
InputStream in =sftp.get(fileName);
BufferedReader buffer =new BufferedReader(new InputStreamReader(in));
String line ="";
while ((line = buffer.readLine()) !=null) {
lines.add(line);
}
}catch (SftpException | IOException e) {
e.printStackTrace();
}finally {
close();
}
return lines;
}
/**
* 下载文件
* @param localDir
* @return
*/
public FiledownLoadFile(String localDir){
connection();
File file =null;
OutputStream out;
try {
file =new File(localDir);
sftp.cd(folderPath);
out =new FileOutputStream(file);
sftp.get(fileName, out);
}catch (SftpException | FileNotFoundException e) {
e.printStackTrace();
}finally {
close();
}
return file;
}
public void close(){
if (sftp !=null) {
sftp =null;
}
if (session !=null) {
session =null;
}
}
public static void main(String[] args) {
SFtpMethod sFtpMethod =new SFtpMethod("",22,"","");
// 显示所有文件名
List fileNames = sFtpMethod.getAllFileNames();
for (String fileName : fileNames) {
System.out.println(fileName);
}
// // 按行读取文件输出
List lines = sFtpMethod.readByLine();
for (String line : lines) {
System.out.println(line);
}
// // 下载文件
sFtpMethod.downLoadFile("/Users/Downloads/check_credit_apply__mcaus_6eqfy");
// // 密钥方式
List fileNamess = sFtpMethod.getAllFileNames("","");
for (String fileName : fileNamess) {
System.out.println(fileName);
}
}
/**
* 身份信息
*/
class MyUserInfoimplements UserInfo{
private Stringpassphrase;
public MyUserInfo(String passphrase) {
this.passphrase = passphrase;
}
@Override
public StringgetPassphrase() {
return null;
}
@Override
public StringgetPassword() {
return null;
}
@Override
public boolean promptPassword(String s) {
return false;
}
@Override
public boolean promptPassphrase(String s) {
return false;
}
@Override
public boolean promptYesNo(String s) {
return false;
}
@Override
public void showMessage(String s) {
}
}
}
通过秘钥方式进行sftp连接,需要在本地生成秘钥:ssh-keygen,然后一路回车或两次输入passphrase。接着在.ssh文件夹下使用命令 ssh-copy-id 账号@118.XX.XX.XX(目标服务器ip),将公钥加入到目标服务器的authorized_keys中,接着登录服务器进行.ssh目录,chmod 664 authorized_keys,赋予权限。如果是mac系统可以使用ssh-keygen -e。
秘钥文件路径keyFile是本地的私钥路径(包含文件名)。下面简单验证一下:
我保持本地私钥文件位置正确的情况下,改变服务器的私钥位置或名字,仍能够正常访问。
在秘钥验证时,我将keyFile路径设置为一个本地不存在的文件的路径,报错如下:
本地私钥不存在我再把参数keyFile变为一个本地存在的文件,但不是私钥文件位置。报错如下:
私钥无效我将passphrase参数设置任意一个值,还是可以成功连接。这一点很疑惑,不知道为啥,但成功了就高兴。
properties.put("StrictHostKeyChecking", "no");StrictHostKeyChecking有三种选项,no、ask、yes。这三个选项代表了不同的级别,yes最高,no最低。在ssh访问服务器的过程中,会将服务器的公钥保存到本地的~/.ssh/known_hosts中,每次访问服务器都会检查此公钥是否发生变化,如果发生了变化,则这三个选项的设置如下:
no:自动将服务器新的公钥保存到known_hosts中,并发出一个警告;
ask:拒绝连接到服务器,且发出一个警告;
yes:拒绝连接到服务器,且不发出警告;
一般在测试环境下使用no,生产环境使用yes或ask。
网友评论