SFTP第一篇——搭建SFTP Server

SFTP第一篇——搭建SFTP Server一、Mac搭建SftpServer1、检查ftp工具打开命令行,输入“ftp–help”,检查是否已经安装ftp工具。如果没有,通过以下命令安装: brewinstalltelnet brewinstallinetutils brewlink–overwriteinetutils 如果没有brew,通过以下命令安装:/usr/bin/…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

一、Mac搭建Sftp Server

1、检查ftp工具

打开命令行,输入“ftp –help”,检查是否已经安装ftp工具。如果没有,通过以下命令安装:

  • brew install telnet

  • brew install inetutils

  • brew link –overwrite inetutils

如果没有brew,通过以下命令安装:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2、运行ftp server

  • sudo -s launchctl load -w /System/Library/LaunchDaemons/ftp.plist
  • sudo -s launchctl unload -w /System/Library/LaunchDaemons/ftp.plist
  • ftp localhost

第一个命令,运行ftp server。同理,第二个是关闭ftp server。第三条命令是连接到该本地ftp server。

3、运行sftp server

在System preferences → shared → Remote login中选择允许访问,即可开启sftp server。然后输入sftp localhost即可连接到该sftp server。

二、搭建嵌入式Sftp Server

1、导入依赖

        <dependency>
            <groupId>org.apache.sshd</groupId>
            <artifactId>sshd-sftp</artifactId>
            <version>2.2.0</version>
        </dependency>

2、EmbeddedSftpServer

@Slf4j
public class EmbeddedSftpServer implements InitializingBean, SmartLifecycle {

    public static final int PORT = 0;

    private final SshServer server = SshServer.setUpDefaultServer();

    private volatile int port;

    private volatile boolean running;

    private DefaultSftpSessionFactory defaultSftpSessionFactory;

    public void setPort(int port) {
        this.port = port;
    }

    public void setDefaultSftpSessionFactory(DefaultSftpSessionFactory defaultSftpSessionFactory) {
        this.defaultSftpSessionFactory = defaultSftpSessionFactory;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        final PublicKey allowedKey = decodePublicKey();
        this.server.setPublickeyAuthenticator((username, key, session) -> key.equals(allowedKey));
        this.server.setPort(this.port);
        this.server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("hostKey.ser").toPath()));
        server.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
        final String pathname = System.getProperty("java.io.tmpdir") + File.separator + "sftpTest" + File.separator;
        log.info("create temp folder :: " + pathname);
        new File(pathname).mkdirs();
        server.setFileSystemFactory(new VirtualFileSystemFactory(Paths.get(pathname)));
    }

    private PublicKey decodePublicKey() throws Exception {
        InputStream stream = new ClassPathResource("/keys/sftp_rsa.pub").getInputStream();
        byte[] keyBytes = StreamUtils.copyToByteArray(stream);
        // strip any newline chars
        while (keyBytes[keyBytes.length - 1] == 0x0a || keyBytes[keyBytes.length - 1] == 0x0d) {
            keyBytes = Arrays.copyOf(keyBytes, keyBytes.length - 1);
        }
        byte[] decodeBuffer = Base64Utils.decode(keyBytes);
        ByteBuffer bb = ByteBuffer.wrap(decodeBuffer);
        int len = bb.getInt();
        byte[] type = new byte[len];
        bb.get(type);
        if ("ssh-rsa".equals(new String(type, "UTF-8"))) {
            BigInteger e = decodeBigInt(bb);
            BigInteger m = decodeBigInt(bb);
            RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);
            return KeyFactory.getInstance("RSA").generatePublic(spec);

        } else {
            throw new IllegalArgumentException("Only supports RSA");
        }
    }

    private BigInteger decodeBigInt(ByteBuffer bb) {
        int len = bb.getInt();
        byte[] bytes = new byte[len];
        bb.get(bytes);
        return new BigInteger(bytes);
    }

    @Override
    public boolean isAutoStartup() {
        return PORT == this.port;
    }

    @Override
    public int getPhase() {
        return Integer.MAX_VALUE;
    }

    @Override
    public void start() {
        try {
            this.server.start();
            log.info("Embedded Sftp Server started");
            this.defaultSftpSessionFactory.setPort(this.server.getPort());
            this.running = true;
        } catch (IOException e) {
            log.error("Embedded Sftp Server starting failure", e);
            throw new IllegalStateException(e);
        }
    }

    @Override
    public void stop(Runnable callback) {
        stop();
        callback.run();
    }

    @Override
    public void stop() {
        if (this.running) {
            try {
                server.stop(true);
                log.info("Embedded Sftp Server stopped");
            } catch (Exception e) {
                log.info("Embedded Sftp Server stop failure", e);
                throw new IllegalStateException(e);
            } finally {
                this.running = false;
            }
        }
    }

    @Override
    public boolean isRunning() {
        return this.running;
    }
}

3、key文件

sftp_rsa(Private key)

-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAzEAf70wmOkBBfvz+92UGc4I+SwVBvICj2wF3VnBP19IN44LD
6cW+/jRoqjaT/qFSELC/UO0wbL9f1+8XOrHekpjP1Ez/CxdM5X9BkrxHoQtgU/fB
gog6iPASqWYxujvPqTxAWPDOYhji7Q1Es5Yc8le5D3AA2Cx5f89X7LFPsdlDC+wa
EpoIdFz3Nrvhr+vufElZNoqQGTpmlmQ8s1gHN7HM8/w5EHkf3KY9OOx1XNWW/zOW
uGo2CNfCmvplYSnokJx3NzSsBOmcXMJWnG1Sv33sqX6Xqx0DpY+hHun+oboZ1cfc
eNlddQONU6IffFiNhFQ3qruBHE8RxyZ7SYaW3QIDAQABAoIBAQCclFgm+eigZVwQ
fuDzRTZR3Lnmhywi1zdGEHStBkKfP/+3typ7j0Xg2MqYGmkQHhmsg+LWpk6mP3u5
LShQrcTj+1Pv++rVVNJ1aT4awE3lLrR1Co0FhWviSLD1vktG6s1CftcRl+GPoGZu
tepCBkVAn3FWXVW4YzftfEV6RV/EBVzZLySXeaQyKl8ln3yEBpOPkevy8uLC20O9
OKDGa30gEP215Kvx1rkvs6jXeMdeH+reEfvyYD8+SMcE60lyY8ntwKhrd/OiZP48
Fqp4kVEBf/u5DSeQbABLCW2uteHAMFzm/weOHDIIBm2aQzmrokw8IYuYiAyTpnDd
yqlJN+99AoGBAOegXlfK/6aVxpeygRatSRD+JI9p/7Hi9ShQ/VCANyc1RTKvDHIA
j5On1Hnwm1czFMr3CPs78MQa8uDlZEa19HbUAEgSp9X6nIPYi5Fo0Q3Fyp1O122S
QAA0mthGiEsneWMgRDordHgGFVoWcDbTWCH61bkisNufK90b/90TXVoPAoGBAOG+
SyW5aJTGHw01vHyNnnMWyloNMwd55vGp7Zhb7m1qUIci8WixJ3Jr1exLhhnc8Bpl
DU2sA4x2r6c1yozNozAw/KkLoa0JFISUg8eqprO0kMg6W9SP57xW2ooUMwEOJbkC
pjlgVcw3AXPfBZwCmujNG0wxc5TVVulgjQk0y1xTAoGBAK9RdjdTYp/vfAq0RPsq
HETtaDTZEX3OgKuMacA13AkkTAUp8+ySOhqUDMJjeODOvC1IQJcQ7pMwpqfNWVIg
RTJwEup6nGjdMPymujVMtfeLv2nEFFFOQn0lVBLhiCYCceGyuZGh9J0oVZ8DntoQ
rAPEPWLNPDpvxx6sI8Vs89rHAoGATLypQuuh92DZ0V3A8v4ZLLpEkxQFkrcHoILJ
N4+Yny0Srr1cHuCJrkWl9Ks/rK8EF5TeTtb4Zdk6oLaSYgbNQGaGnNhNX0rE5MSv
f0ItZM0uokHkUX+RoN5Nb76qD+PFQvz5kGuE/uR74+2eNIhWLGj8rIvq5F8ZKkAd
8VE3B+0CgYEAnrh436/L4s9RI9kbKfd99PEl87DFOYB3/v4g4n4Xoi9843dYDjgX
bl1JLbD2jv5HYMs55sHK9Rz/aWiTTDCoONkHL5b84ZDrPJnKzzzwMAND4RivJBYK
ORr+P2OrWEIt57CvLxTYB2RjHQdJ7+r8fxjyRGkkkxJScdsDhCBYisk=
-----END RSA PRIVATE KEY-----

sftp_rsa.pub(public key)

AAAAB3NzaC1yc2EAAAADAQABAAABAQDMQB/vTCY6QEF+/P73ZQZzgj5LBUG8gKPbAXdWcE/X0g3jgsPpxb7+NGiqNpP+oVIQsL9Q7TBsv1/X7xc6sd6SmM/UTP8LF0zlf0GSvEehC2BT98GCiDqI8BKpZjG6O8+pPEBY8M5iGOLtDUSzlhzyV7kPcADYLHl/z1fssU+x2UML7BoSmgh0XPc2u+Gv6+58SVk2ipAZOmaWZDyzWAc3sczz/DkQeR/cpj047HVc1Zb/M5a4ajYI18Ka+mVhKeiQnHc3NKwE6ZxcwlacbVK/feypfperHQOlj6Ee6f6huhnVx9x42V11A41Toh98WI2EVDequ4EcTxHHJntJhpbd

4、SftpTestUtils

public class SftpTestUtils {

    private static final String SFTP_TEMP_FOLDER = "sftpTempFolder";

    public static void createTestFiles(RemoteFileTemplate<LsEntry> template, final String... fileNames) {
        if (template != null) {
            final ByteArrayInputStream stream = new ByteArrayInputStream("TestData".getBytes());
            template.execute((SessionCallback<LsEntry, Void>) session -> {
                try {
                    session.mkdir(SFTP_TEMP_FOLDER);
                } catch (Exception e) {
                    assertThat(e.getMessage(), containsString("failed to create"));
                }
                for (int i = 0; i < fileNames.length; i++) {
                    stream.reset();
                    session.write(stream, SFTP_TEMP_FOLDER + "/" + fileNames[i]);
                }
                return null;
            });
        }
    }

    public static void cleanUp(RemoteFileTemplate<LsEntry> template, final String... fileNames) {
        if (template != null) {
            template.execute((SessionCallback<LsEntry, Void>) session -> {
                for (int i = 0; i < fileNames.length; i++) {
                    try {
                        // delete temp file
                        session.remove(SFTP_TEMP_FOLDER + "/" + fileNames[i]);
                    } catch (IOException e) {
                    }
                }
                // delete temp folder
                session.rmdir(SFTP_TEMP_FOLDER);
                return null;
            });
        }
    }

    public static boolean fileExists(RemoteFileTemplate<LsEntry> template, final String... fileNames) {
        if (template != null) {
            return template.execute(session -> {
                ChannelSftp channel = (ChannelSftp) session.getClientInstance();
                for (int i = 0; i < fileNames.length; i++) {
                    try {
                        SftpATTRS stat = channel.stat(SFTP_TEMP_FOLDER + "/" + fileNames[i]);
                        if (stat == null) {
                            System.out.println("stat returned null for " + fileNames[i]);
                            return false;
                        }
                    } catch (SftpException e) {
                        System.out.println("Remote file not present: " + e.getMessage() + ": " + fileNames[i]);
                        return false;
                    }
                }
                return true;
            });
        } else {
            return false;
        }
    }

}

该工具类用来创建一些临时目录和文件,供测试类调用。

5、SftpTestConfig配置类

@TestConfiguration
public class SftpTestConfig {
    @Bean
    public DefaultSftpSessionFactory defaultSftpSessionFactory() {
        DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
        factory.setPort(0);
        factory.setHost("localhost");
        factory.setUser("user");
        factory.setAllowUnknownKeys(true);
        factory.setPrivateKey(new ClassPathResource("/keys/sftp_rsa"));
        factory.setPrivateKeyPassphrase("password");
        return factory;
    }

    @Bean
    public CachingSessionFactory cachingSessionFactory() {
        return new CachingSessionFactory(defaultSftpSessionFactory());
    }

    @Bean
    public EmbeddedSftpServer embeddedSftpServer() {
        EmbeddedSftpServer sftpServer = new EmbeddedSftpServer();
        sftpServer.setPort(0);
        sftpServer.setDefaultSftpSessionFactory(defaultSftpSessionFactory());
        return sftpServer;
    }
}

6、测试类

@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SftpTestConfig.class}, loader = AnnotationConfigContextLoader.class)
public class SpringSftpTest {

    @Autowired
    private CachingSessionFactory cachingSessionFactory;

    private RemoteFileTemplate<ChannelSftp.LsEntry> template;

    private String file1 = "a.txt";
    private String file2 = "b.txt";
    private String file3 = "c.txt";

    @Before
    public void init() {
        template = new RemoteFileTemplate<>(cachingSessionFactory);
        // create test file
        SftpTestUtils.createTestFiles(template, file1, file2, file3);
    }

    @After
    public void destroy() {
        // delete all temp file and folder
        SftpTestUtils.cleanUp(template, file1, file2, file3);
    }

    @Test
    public void testListFiles() {
        Assert.assertTrue(template.exists("/sftpTempFolder"));
        ChannelSftp.LsEntry[] lsEntries = template.list("/sftpTempFolder");
        // bypass '.' and '..' folder
        Arrays.stream(lsEntries).filter(lsEntry -> !lsEntry.getFilename().startsWith(".")).forEach(lsEntry -> {
            log.info(lsEntry.getLongname());
            Assert.assertTrue(lsEntry.getFilename().endsWith(".txt"));
        });
    }
}

这里采用Spring-integration-sftp做sftp开发,jsch的话也一样,配置好host、port等,连接到嵌入式sftp server即可。

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/179614.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(3)


相关推荐

  • CF 1039D You Are Given a Tree && CF1059E Split the Tree 的贪心解法[通俗易懂]

    CF 1039D You Are Given a Tree && CF1059E Split the Tree 的贪心解法[通俗易懂]CF 1039D You Are Given a Tree && CF1059E Split the Tree 的贪心解法

  • 2019最新Web前端经典面试试题及答案-史上最全前端面试题(含答案)

    2019最新Web前端经典面试试题及答案-史上最全前端面试题(含答案)近期总结一一些面试题都是企业的面试题笔记题感觉薪资10k下的都会出笔试题特别高的薪资都是直接技术面试或者是现场编程总结很多人的面试题,后期会对于单个知识点再说笔记详细讲解。部分都是百度的答案,不是特全面的,可以自己找下同时分享一个自己录制的CSS3动画特效经典案例【推荐教程】–后期会更新vue框架微信小程序等内容。https://ke.qq.com/cou…

  • 不止一个背包的背包问题_超级背包怎么使用方法

    不止一个背包的背包问题_超级背包怎么使用方法有 N 个物品和一个容量是 V 的背包。物品之间具有依赖关系,且依赖关系组成一棵树的形状。如果选择一个物品,则必须选择它的父节点。如下图所示:如果选择物品5,则必须选择物品1和2。这是因为2是5的父节点,1是2的父节点。每件物品的编号是 i,体积是 vi,价值是 wi,依赖的父节点编号是 pi。物品的下标范围是 1…N。求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。输出最大价值。输入格式第一行有两个整数 N,V,用空格隔开,分别表示物品个数和背包容量。接下来有 N

  • hashcode方法实现_java重写hashcode方法

    hashcode方法实现_java重写hashcode方法详解Java中hashCode的作用以下是关于HashCode的官方文档定义:hashcode方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable提供的哈希表。hashCode的常规协定是:在Java应用程序执行期间,在同一对象上多次调用hashCode方法时,必须一致地返回相同的整数,前提是对象上equals比较中所用的信息没有…

  • centos7安装python3.7_python软件安装步骤

    centos7安装python3.7_python软件安装步骤Centos7安装Python3.8详细教程Centos7安装Python3.8详细教程安装编译相关工具下载python安装包编译安装python创建软连接更改yum配置Centos7安装Python3.8详细教程安装编译相关工具yum-ygroupinstall”Developmenttools”yum-yinstallzlib-develbzip2-developenssl-develncurses-develsqlite-develreadline-develtk-d

  • WIN-CE系统架构

    WIN-CE系统架构分为素部分:硬件层、OEM层、操作系统层、应用层http://hovertree.com/hvtart/bjae/oy9pqb94.htm硬件层:由CPU、存储器、I/

    2021年12月27日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号