大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新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账号...