Apache MINA SSHD 是一个基于 Java 的 SSH 服务器和客户端实现,它是 Apache MINA 项目的一部分,提供了完整的 SSH 协议支持。

主要特性

  1. SSH 协议支持

    • 支持 SSH2 协议

    • 兼容大多数 SSH 客户端

    • 支持多种加密算法和密钥交换方法

  2. 服务器功能

    • 可嵌入的 SSH 服务器

    • 支持密码认证和公钥认证

    • 支持端口转发

    • 可自定义的 shell 和命令执行

  3. 客户端功能

    • 完整的 SSH 客户端实现

    • 支持交互式和非交互式会话

    • 支持 SCP 和 SFTP 文件传输

  4. 具体配置

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClient;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.common.SftpConstants;
import org.springframework.lang.NonNull;
import java.io.ByteArrayOutputStream;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;/*** SshClient服务类** @author gengzhy* @since 2025/5/29 16:57*/
@Slf4j
public class SshClientService {private final SshClient sshClient;private final SftpProperties properties;public SshClientService(SshClient sshClient, SftpProperties properties) {this.sshClient = sshClient;this.properties = properties;}/*** 读取文件** @param filePath - 文件路径* @return - Bytes*/public byte[] readOnce(@NonNull String filePath) throws IOException {return executeInternal(session -> {try (SftpClient sftpClient = sftpClient(session)) {SftpClient.Attributes stat = beforeReadCheck(sftpClient, filePath);try (InputStream in = new BufferedInputStream(sftpClient.read(filePath))) {ByteArrayOutputStream out = new ByteArrayOutputStream((int) stat.getSize());byte[] buffer = new byte[8192];int read;while ((read = in.read(buffer, 0, buffer.length)) != -1) {out.write(buffer, 0, read);}return out.toByteArray();}} catch (IOException e) {Throwable ex = getRootCause(e);log.error("sftp 读取文件异常: {}", ex.getMessage(), ex);throw new RuntimeException(ex.getMessage(), ex);}});}/*** 读取文件** @param filePath - 文件路径* @return - Bytes*/public List<String> readLines(@NonNull String filePath) throws IOException {return readLines(filePath, null);}/*** 读取文件** @param filePath     - 文件路径* @param lineConsumer - 读取的数据行消费者* @return - Bytes*/public List<String> readLines(@NonNull String filePath, Consumer<String> lineConsumer) throws IOException {return executeInternal(session -> {try (SftpClient sftpClient = sftpClient(session)) {beforeReadCheck(sftpClient, filePath);try (BufferedReader br = new BufferedReader(new InputStreamReader(sftpClient.read(filePath), StandardCharsets.UTF_8))) {List<String> data = new ArrayList<>();String line;while ((line = br.readLine()) != null) {data.add(line);if (lineConsumer != null) {lineConsumer.accept(line);}}return data;}} catch (IOException e) {Throwable ex = getRootCause(e);log.error("sftp 读取文件异常: {}", ex.getMessage(), ex);throw new RuntimeException(ex.getMessage(), ex);}});}/*** 创建文件** @param filePath - 文件路径*/public void writeOnce(@NonNull String filePath, byte[] data) throws IOException {executeInternal(session -> {try (SftpClient sftpClient = sftpClient(session)) {mkDirsIfNotExists(sftpClient, getFileParentPath(filePath));try (SftpClient.CloseableHandle handle = sftpClient.open(filePath, SftpClient.OpenMode.Create, SftpClient.OpenMode.Write, SftpClient.OpenMode.Read)) {sftpClient.write(handle, 0L, data);}return null;} catch (IOException e) {Throwable ex = getRootCause(e);log.error("sftp 创建文件异常: {}", ex.getMessage(), ex);throw new RuntimeException(ex.getMessage(), ex);}});}/*** 递归创建目录(等效于 mkdir -p)** @param sftpClient SFTP 客户端* @param dirPath    目标路径(如 "/a/b/c")*/public void mkDirsIfNotExists(SftpClient sftpClient, String dirPath) throws IOException {if (dirPath == null) {return;}String[] parts = dirPath.split("/");StringBuilder currentPath = new StringBuilder();for (String part : parts) {if (part.isEmpty()) {continue;}currentPath.append("/").append(part);String path = currentPath.toString();if (stat(sftpClient, path) == null) {sftpClient.mkdir(path);}}}/*** 提供一个便于扩展的内容部执行方法,主要是基于{@link ClientSession}对象的一些列操作* <p>* 如:* 创建sftp客户端对象:{@link SftpClientFactory#instance()#createSftpClient(ClientSession)}* 创建shell执行命令对象:{@link ClientSession#createExecChannel(String)}}** @param execCall - 基于{@link ClientSession}对象的回调* @param <T>      - 返回数据类型* @return - obj*/public <T> T executeInternal(Function<ClientSession, T> execCall) throws IOException {try (ClientSession session = session()) {return execCall != null ? execCall.apply(session) : null;} catch (IOException e) {log.error("创建ssh会话异常·: {}", e.getMessage(), e);throw new IOException("创建ssh会话异常: " + e.getMessage(), e);}}private SftpClient.Attributes beforeReadCheck(SftpClient sftpClient, String filePath) {SftpClient.Attributes stat = stat(sftpClient, filePath);if (stat == null) {throw new RuntimeException("文件不存在【{" + filePath + "}】");}Asserts.isTrue(stat.isRegularFile(), "不支持的文件类型:" + FileType.getByActualType(stat.getType()));Asserts.isTrue(stat.getSize() <= Integer.MAX_VALUE, "文件过大");return stat;}private String getFileParentPath(String filePath) {String path = filePath.replaceAll("[\\\\/]+", "/");int index = path.lastIndexOf('/');return index == -1 ? null : path.substring(0, index);}/*** 获取文件信息,不存在返回null** @param sftpClient - sftp客户端* @param filePath   - 文件路径*/private SftpClient.Attributes stat(SftpClient sftpClient, String filePath) {try {return sftpClient.stat(filePath);} catch (IOException e) {return null;}}private SftpClient sftpClient(ClientSession session) throws IOException {return SftpClientFactory.instance().createSftpClient(session);}private ClientSession session() throws IOException {synchronized (sshClient) {if (!sshClient.isStarted()) {sshClient.start();}}ClientSession session = sshClient.connect(properties.getUsername(), properties.getHost(), properties.getPort()).verify(properties.getConnectTimeout()).getSession();session.addPasswordIdentity(properties.getPassword());session.auth().verify(properties.getAuthTimeout());return session;}private Throwable getRootCause(Throwable ex) {while (ex.getCause() != null) {ex = ex.getCause();}return ex;}@Getter@AllArgsConstructorprivate enum FileType {file(SftpConstants.SSH_FILEXFER_TYPE_REGULAR),dir(SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY),symlink(SftpConstants.SSH_FILEXFER_TYPE_SYMLINK),special_file(SftpConstants.SSH_FILEXFER_TYPE_SPECIAL),SOCKET(SftpConstants.SSH_FILEXFER_TYPE_SOCKET),unknown(SftpConstants.SSH_FILEXFER_TYPE_UNKNOWN),;private final int actualType;public static FileType getByActualType(int actualType) {return Arrays.stream(FileType.values()).filter(item -> item.actualType == actualType).findFirst().orElseThrow(() -> new RuntimeException("Unknown file type: " + actualType));}}
}
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.time.Duration;@Getter
@Setter
@ConfigurationProperties(prefix = "sftp")
public class SftpProperties {/*** 主机IP*/private String host = "127.0.0.1";/*** 主机端口,默认22*/private int port = 22;/*** 用户名*/private String username = "";/*** 登录密码*/private String password = "";/*** 连接超时(ms),默认5000ms*/private Duration connectTimeout = Duration.ofMillis(5000);/*** 认证超时(ms),默认10000ms*/private Duration authTimeout = Duration.ofMillis(10000);
}
import org.apache.sshd.client.SshClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@ConditionalOnClass(SshClient.class)
@Configuration
@EnableConfigurationProperties(SftpProperties.class)
public class SshClientConfiguration {@BeanSshClientService sshClientService(SftpProperties properties) {return new SshClientService(SshClient.setUpDefaultClient(), properties);}
}
sftp:host: 127.0.0.1port: 22username: demopassword: pwdconnect-timeout: 5sauth-timeout: 5s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/913108.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/913108.shtml
英文地址,请注明出处:http://en.pswp.cn/news/913108.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Excel 如何让数据自动按要求排序或筛选?

让数据按要求排序和筛选是Excel数据处理的基础核心功能&#xff0c;也是进行有效分析前必做的准备工作。下面我们分开讲解这两个功能。 一、排序 (Sort)&#xff1a;让数据井井有条 排序的目的是重新排列数据行的顺序&#xff0c;以便更好地观察和比较。 1. 快速单列排序 (最…

Django 安装使用教程

一、Django 简介 Django 是一个高级 Python Web 框架&#xff0c;鼓励快速开发和简洁实用的设计。它内置 ORM、认证系统、后台管理、表单处理、路由控制等功能&#xff0c;广泛用于开发企业级网站、内容管理系统、电商平台等。 二、环境准备 2.1 安装 Python Django 基于 Py…

前沿交叉:Fluent与深度学习驱动的流体力学计算体系

基础模块 流体力学方程求解 1、不可压缩N-S方程数值解法&#xff08;有限差分/有限元/伪谱法&#xff09; Fluent工业级应用&#xff1a;稳态/瞬态流、两相流仿真&#xff08;圆柱绕流、入水问题&#xff09; Tecplot流场可视化与数据导出 2、CFD数据的AI预处理 基于P…

五、Flutter动画

目录1. Flutter 中动画的基本概念是什么&#xff1f;2. 解释 AnimationController 和 Tween 的作用3. 如何实现一个补间&#xff08;Tween&#xff09;动画&#xff1f;4. 什么是隐式动画&#xff1f;举例说明5. 如何实现自定义复杂动画&#xff1f;1. Flutter 中动画的基本概念…

全网唯一/Qt结合ffmpeg实现手机端采集摄像头推流到rtsp或rtmp/可切换前置后置摄像头/指定分辨率帧率

一、前言说明 之前已经实现了Qt结合ffmpeg在安卓上运行&#xff0c;所有在win上的功能&#xff0c;在安卓上都已经实现&#xff0c;比如编码保存到MP4文件&#xff0c;正常解码音视频文件播放等&#xff0c;唯独还差一个功能&#xff0c;尽管用的不多&#xff0c;但是还是有一…

Install Ubuntu 24.04 System

1.制作安装镜像盘&#xff08;U盘&#xff09; 下载rufus制作工具(网址&#xff1a;https://www.xiaomoxz.com/nexus/bi1/rufus4.shtml?bd_vid8643969197265870719&#xff09; 2. 设置U盘启动&#xff1a; F2进入BIOS 3. Install Ubuntu 24.04 Ubuntu下载地址&#xff1a;…

solidjs 处理复杂类型的响应式

solidjs 处理复杂类型的响应式 在 solidjs 里响应式一般直接用 createSignal 就可以&#xff0c;但 createSignal 一般用于基础数据类型。 虽然复杂类型也是可以使用&#xff0c;但基于起细粒度响应性的特性。 一般复杂的数据使用 createSignal 就不是那么友好了。 所以 cre…

爬虫技术-获取浏览器身份认证信息(如 Cookie、Token、Session 等)

方法一&#xff1a;通过浏览器开发者工具查看和提取 Cookie / Token &#x1f4cc; 示例场景&#xff1a; 你在使用一个网站时已经登录了&#xff0c;想看看这个网站是如何保存你的身份凭证的。 &#x1f527; 操作过程&#xff1a; 打开浏览器&#xff08;例如 Chrome&#xf…

[密码学实战]GMT 0136-2024《密码应用HTTP接口规范》解析

[密码学实战]GM/T 0136-2024《密码应用HTTP接口规范》解析国家密码管理局于2025年7月1日正式实施GM/T 0136-2024标准&#xff0c;该规范首次统一了密码服务的HTTP接口设计&#xff0c;为国产密码技术的规模化应用铺平道路。本文结合标准原文&#xff0c;深入剖析其技术细节并给…

Docker 国内镜像列表(免费长期)

Docker 可用镜像源列表&#xff08;7月1日更新-长期维护&#xff09;_dockerhub国内镜像源列表-CSDN博客

BlenderFBXExporter 导出fbx被修改问题

1&#xff09; 解决增加A节点的问题 https://github.com/A-Ribeiro/CustomBlenderFBXExporter 2&#xff09;找出blendshape 不一致&#xff0c;生成blendshape key name映射map 文件compare.txt C:\Users\49938\Documents\DazToUnreal\zhang01\UpdatedFBX\zhang01_fix7.fbx…

AI时代下的IT服务管理转型:趋势、挑战与破局之道

近年来&#xff0c;人工智能&#xff08;AI&#xff09;与自动化技术的迅猛发展&#xff0c;正以前所未有的速度重塑企业运营的各个层面。特别是在IT服务管理&#xff08;ITSM&#xff09;领域&#xff0c;AI的介入不仅提高了问题响应效率&#xff0c;也推动了组织从“被动响应…

三体融合实战:Django+讯飞星火+Colossal-AI的企业级AI系统架构

目录 技术栈关键词&#xff1a;Django 5.0 讯飞星火4.0Ultra Colossal-AI 1.2 WebSocket 联邦学习 ⚡ 核心架构设计 &#x1f6e0;️ 一、Django深度集成讯飞星火API&#xff08;免费版&#xff09; 1. 获取API凭证 2. 流式通信改造&#xff08;解决高并发阻塞&#xff09…

多模态数据融合预警:从IoT传感器到卫星监测的可视化方案升级

你有没有想过&#xff0c;为什么有些城市在暴雨来临时能提前数小时发布内涝预警&#xff0c;而有些地方却只能“等水来了才反应”&#xff1f; 背后的关键&#xff0c;就是多模态数据融合预警系统——它把来自IoT传感器、无人机、地面雷达、气象站、甚至卫星的数据整合在一起&a…

面试八股---css

2、css 2.1 说说你对盒子模型的理解 是什么 当对一个文档进行布局&#xff08;layout&#xff09;的时候&#xff0c;浏览器的渲染引擎会根据标准之一的 CSS 基础框盒模型&#xff08;CSS basic box model&#xff09;&#xff0c;将所有元素表示为一个个矩形的盒子&#xf…

day52-硬件学习之RTC及ADC

一、RTCRTC&#xff08;实时时钟&#xff09;&#xff1a;非易失性在IMX6ULL内部SNVS&#xff08;安全的非易失性存储器&#xff09;提供RTC功能&#xff1b;原理图&#xff1a;二、ADC 2.1 基本概念ADC(模拟数字转换器)&#xff1a;用于将连续变化的模拟信号转换为离散的数字信…

Web 项目如何自动化测试?

Web 项目的自动化测试可以通过 UI自动化 和 接口自动化 结合实现&#xff0c;提高测试效率和覆盖率。以下是关键方法和工具&#xff1a; 【自动化测试】从基础到实战基于Pytest自动化/python自动化的详细教程&#xff01;1. UI自动化测试&#xff08;前端交互&#xff09; 适用…

Java连接阿里云MaxCompute例

要使用Java连接阿里云MaxCompute&#xff08;原名ODPS&#xff09;数据库&#xff0c;您可以遵循以下步骤进行配置和编程&#xff1a; 1. 添加依赖 确保您的项目中包含了MaxCompute JDBC驱动的依赖。如果您使用Maven&#xff0c;可以在pom.xml中添加如下依赖&#xff1a; &l…

【网络与系统安全】强制访问控制——BLP模型

一、模型背景与定义 BLP&#xff08;Bell-LaPadula&#xff09;模型是由David Bell和Len Adula在1973年提出的强制访问控制&#xff08;MAC&#xff09;模型&#xff0c;是最早的计算机安全模型之一&#xff0c;主要用于解决多用户系统中的信息机密性保护问题&#xff0c;尤其…

HTTPS详解:原理 + 加解密过程 + 面试问答

一、HTTP 与 HTTPS 的区别 项目HTTPHTTPS全称HyperText Transfer ProtocolHyperText Transfer Protocol Secure端口80443协议层应用层应用层 TLS&#xff08;安全层&#xff09;加密方式明文传输加密传输&#xff08;TLS&#xff09;安全性易被劫持、中间人攻击可加密、防篡改…