You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向Apache SSHD服务器写入文件?技术实现问询

你的Apache SSHD服务器文件操作问题解答

嘿,我来帮你把这个问题理清楚~首先直接给你答案:是的,向Apache SSHD服务器写入/读取文件确实需要SSH客户端——毕竟SSH是典型的客户端-服务器协议,你的服务器端代码只是负责监听连接、处理认证、响应客户端的文件操作请求,本身不会主动生成或写入文件。

你当前的代码已经搭好了SSH服务器的基础框架(认证、SCP命令支持),但缺少了关键的文件系统绑定逻辑——用户登录后没有对应的文件目录可以操作,所以客户端连上来后根本没法上传文件。下面是具体的解决步骤和代码修改:


1. 核心修改:绑定文件系统

Apache SSHD提供了几种文件系统实现,你可以根据需求选择:

  • 本地文件系统:用NativeFileSystemFactory,直接映射到服务器的本地磁盘目录
  • 内存文件系统:用VirtualFileSystemFactory,完全在内存中操作,符合你做mock后端的需求

修改后的完整SSHServer代码

package com.example.sshd;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.scp.ScpCommandFactory;
import org.apache.sshd.server.filesystem.NativeFileSystemFactory;
import org.apache.sshd.server.filesystem.VirtualFileSystemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SSHServer {
    private SshServer sshServer;
    private static final Logger logger = LoggerFactory.getLogger(SSHServer.class);

    public SSHServer() throws IOException {
        sshServer = SshServer.setUpDefaultServer();
        sshServer.setHost("127.0.0.1");
        sshServer.setPort(2222); // 指定端口,避免和系统SSH冲突
        // 生成临时主机密钥文件
        sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Files.createTempFile("host_file", ".ser").toAbsolutePath()));
        
        // 配置SCP命令支持
        sshServer.setCommandFactory(new ScpCommandFactory());
        
        // 密码认证逻辑
        sshServer.setPasswordAuthenticator((username, password, serverSession) -> {
            logger.debug("authenticating: {} password: {}", username, password);
            return username != null && "changeit".equals(password);
        });

        // 方案1:使用本地文件系统(适合测试时持久化文件)
        // 指定用户根目录,比如当前目录下的ssh-test目录
        Path localRoot = Paths.get(System.getProperty("user.dir"), "ssh-test");
        Files.createDirectories(localRoot); // 确保目录存在
        sshServer.setFileSystemFactory(new NativeFileSystemFactory());
        // 为每个用户设置根目录(这里所有用户都用同一个根目录)
        sshServer.setFileSystemFactory(session -> new NativeFileSystemFactory.NativeFileSystemView(localRoot, session));

        // 方案2:使用内存文件系统(适合mock后端,重启后文件消失)
        // VirtualFileSystemFactory virtualFs = new VirtualFileSystemFactory();
        // virtualFs.setDefaultHomeDir("/"); // 设置内存根目录
        // sshServer.setFileSystemFactory(virtualFs);
    }

    public void startServer() throws IOException{
        sshServer.start();
        logger.info("SSH Server started on {}:{}", sshServer.getHost(), sshServer.getPort());
    }

    public void stopServer() throws IOException {
        sshServer.stop();
        logger.info("SSH Server stopped");
    }

    // 测试用主方法
    public static void main(String[] args) throws IOException, InterruptedException {
        SSHServer server = new SSHServer();
        server.startServer();
        // 保持服务器运行,按回车停止
        System.in.read();
        server.stopServer();
    }
}

2. 如何向服务器写入文件?

有两种常用方式:

方式1:用命令行客户端(比如scp)

启动你的SSHServer后,在终端用scp命令上传文件:

# 上传本地文件到服务器的根目录(对应我们配置的ssh-test目录或内存根目录)
scp -P 2222 /path/to/local/file.txt user@127.0.0.1:/file.txt
# 下载服务器文件到本地
scp -P 2222 user@127.0.0.1:/file.txt /path/to/local/destination.txt

(这里的user可以是任意非空用户名,只要密码是changeit就能通过认证)

方式2:用Java客户端代码(比如Apache SSHD的SshClient)

如果你的测试工具需要程序化上传文件,可以用Apache SSHD自带的客户端库:

import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.scp.ScpClient;
import java.io.IOException;
import java.nio.file.Paths;

public class SshFileUploader {
    public static void main(String[] args) throws IOException {
        try (SshClient client = SshClient.setUpDefaultClient()) {
            client.start();
            // 连接服务器
            client.connect("127.0.0.1", 2222).verify();
            // 认证
            client.authPassword("test-user", "changeit").verify();
            
            // 上传文件
            try (ScpClient scpClient = client.createScpClient()) {
                // 本地文件路径 -> 服务器路径
                scpClient.upload(Paths.get("/path/to/local/file.txt"), "/uploaded-file.txt");
                // 下载文件
                scpClient.download("/uploaded-file.txt", Paths.get("/path/to/local/downloaded.txt"));
            }
            client.disconnect().verify();
        } finally {
            client.stop();
        }
    }
}

3. 适配你的Camel测试场景

针对你的两个核心使用场景,这样配合Camel路由:

  • 场景1:上传文件 → Camel下载
    1. 用客户端上传文件到SSH服务器的/input目录
    2. Camel配置scp组件路由:from("scp://127.0.0.1:2222/input?username=test-user&password=changeit") 来监听并下载文件
  • 场景2:上传文件 → Camel转移/转换 → 下载验证
    1. 客户端上传文件到SSH服务器的/input目录
    2. Camel路由监听/input,处理后转移到/output目录:
      from("scp://127.0.0.1:2222/input?username=test-user&password=changeit")
          .process(exchange -> {
              // 这里添加你的文件转换逻辑
          })
          .to("scp://127.0.0.1:2222/output?username=test-user&password=changeit");
      
    3. 客户端从/output目录下载文件,验证转换结果

内容的提问来源于stack exchange,提问作者Dmytro Chasovskyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:52:43