工作小记01:Java sftp通过用户名密码读取目标服务器上的文件并对文件内容做逻辑处理

发布时间:2024年01月19日

2024.1.17 晚 小雨

前言:我们可以慢慢向前走,但绝对不能后退

最近有这样一个需求,在某台服务器上有个文件,文件路径为:/ftppub/xx/年月日/xxx.txt,这个文件每天都会更新,文件路径的日期目录也会随之更改。文件内容为:xx|xx|xx??有 n 行这样的数据,每一列代表某个字段的值。我需要校验当前某个字段(文件的每一行的第三个字段)的值在该文件中是否存在。

1、引入依赖

<dependency>
   <groupId>com.jcraft</groupId>
   <artifactId>jsch</artifactId>
   <version>0.1.55</version>
</dependency>

2、上代码

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;

/**
 * sftp工具类
 *
 * @author mltang
 * @since JDK8
 */
@Slf4j
public class SftpUtil {
  
    private static ChannelSftp sftp = null;
    private static Session session = null;

    /**
     * 连接sftp服务器
     *
     * @param privateKey
     * @return
     */
    public static ChannelSftp sftpConnect(String host, int port, String username, String password, String privateKey) throws SftpException {
        try {
            JSch jsch = new JSch();
            if (!StringUtils.isEmpty(privateKey)) {
                jsch.addIdentity(privateKey);// 设置私钥
            }
            //用户名,主机,端口号
            session = jsch.getSession(username, host, port);
            //密码
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            // 设置timeout时间
            session.setTimeout(30000);
            session.connect();
            Channel channel = session.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
        } catch (Exception e) {
            log.error("连接sftp失败", e);
            log.error("ip{},port{}", host, port);
            throw new SftpException(500, "连接sftp失败", e);
        }
        return sftp;
    }

    /**
     * ftp读取文件内容并做业务逻辑处理
     * @param ftpPath 文件路径
     * @param fileName 文件名
     * @param taskDate 文件日期
     * @param targetUserId 字段用户编号
     * @return
     * @throws SftpException
     * @throws IOException
     */
    public static boolean getFtpData(String ftpPath, String fileName, String taskDate, String targetUserId) throws SftpException, IOException {
        BufferedReader br = null;
        //连接ftp
        if (null == sftp) {
            return false;
        }
        String dateStr = StringUtils.isEmpty(taskDate) ? taskDate.replaceAll("-", "") : getYesterday();
        String directory = "/" + dateStr + "/";
        try {
            //下载文件
            sftp.cd(ftpPath + directory);
            br = new BufferedReader(new InputStreamReader(sftp.get(fileName), StandardCharsets.UTF_8));
            String line;
            while ((line = br.readLine()) != null) {
                String[] cells = line.split("\\|");
                if(!StringUtils.isEmpty(cells)){
                    return cells[2].equals(targetUserId);
                }
            }
        } catch (Exception e) {
            log.error(fileName + "文件读取异常{}", Arrays.toString(e.getStackTrace()));
        } finally {
            assert br != null;
            br.close();
            closeChannel();
        }
        return false;
    }

    /**
     * 关闭ftp连接
     */
    public static void closeChannel() {
        if (sftp != null) {
            sftp.disconnect();
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }

    /**
     * 获取当前日期的前一天日期
     * @return
     */
    public static String getYesterday() {
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, -24);
        String yesterdayDate = dateFormat.format(calendar.getTime());
        System.out.println(yesterdayDate);
        return yesterdayDate;
    }
}

3、了解一下 privateKey

密钥登录无需用户设置密码,通过rsa密钥对加解密验证,在客户端和服务器端建立安全的连接,简单地说,public key 放在服务器端,private key放在客户端。

客户端发起请求连接

服务器根据请求用户名识别对应客户端公钥,sshd 服务产生一个随机数,用?public key进行加密后,发回到客户端

客户端用?private key解密得到该随机数,客户端将解密后的随机数发回服务器端,

服务端进行匹配,匹配成功认证通过,允许登录。

这种方式避免了密码暴力破解尝试的危险,当然密钥认证因为有加解密和随机数传输验证的过程,连接耗时自然比密码方式长些。

文章来源:https://blog.csdn.net/2401_82540550/article/details/135662372
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。