From d56240cb418d65274a4facb8f25d34cebc47a2eb Mon Sep 17 00:00:00 2001 From: Ng Yat Yan Date: Sun, 13 Oct 2024 18:14:07 +0800 Subject: [PATCH] V1.1.1 Only one session is allowed. New session will override the old. --- conf/log4j2.xml | 4 +- pom.xml | 2 +- .../com/example/sshd/config/AppConfig.java | 21 +++++++++ .../com/example/sshd/config/SshConfig.java | 11 +++-- .../sshd/core/EchoSessionListener.java | 46 +++++++++++++++++++ 5 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/example/sshd/config/AppConfig.java create mode 100644 src/main/java/com/example/sshd/core/EchoSessionListener.java diff --git a/conf/log4j2.xml b/conf/log4j2.xml index 6b237ca..f0fde93 100644 --- a/conf/log4j2.xml +++ b/conf/log4j2.xml @@ -26,10 +26,10 @@ - + - + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3986876..4a91e89 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.example.sshd echo-sshd-server - 1.1.0 + 1.1.1 ECHO SSH SERVER Learning Apache Mina SSHD library diff --git a/src/main/java/com/example/sshd/config/AppConfig.java b/src/main/java/com/example/sshd/config/AppConfig.java new file mode 100644 index 0000000..cbc418a --- /dev/null +++ b/src/main/java/com/example/sshd/config/AppConfig.java @@ -0,0 +1,21 @@ +package com.example.sshd.config; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.sshd.common.Session; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +@Configuration +public class AppConfig { + + @Bean + @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) + public Map remoteSessionMapping() { + return Collections.synchronizedMap(new HashMap<>()); + } +} diff --git a/src/main/java/com/example/sshd/config/SshConfig.java b/src/main/java/com/example/sshd/config/SshConfig.java index 14ad355..710291b 100644 --- a/src/main/java/com/example/sshd/config/SshConfig.java +++ b/src/main/java/com/example/sshd/config/SshConfig.java @@ -4,9 +4,9 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; import java.util.Properties; -import org.apache.commons.lang3.StringUtils; import org.apache.sshd.SshServer; import org.apache.sshd.server.PasswordAuthenticator; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; @@ -21,6 +21,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; +import com.example.sshd.core.EchoSessionListener; import com.example.sshd.core.EchoShellFactory; import com.example.sshd.core.OnetimeCommand; @@ -35,8 +36,8 @@ public class SshConfig { @Value("${ssh-server.private-key.location}") private String pkLocation; - @Value("${ssh-server.root.username:root}") - private String rootUsername; + @Value("${ssh-server.login.usernames:root}") + private String[] usernames; @Value("${ssh-server.hash-replies.location}") private String hashReplies; @@ -57,12 +58,14 @@ public class SshConfig { @Override public boolean authenticate(final String username, final String password, final ServerSession session) { logger.info("Login Attempt: username = {}, password = {}", username, password); - return StringUtils.equals(username, rootUsername); + return Arrays.asList(usernames).contains(username); } }); sshd.setShellFactory(applicationContext.getBean(EchoShellFactory.class)); sshd.setCommandFactory(command -> applicationContext.getBean(OnetimeCommand.class, command)); + sshd.start(); + sshd.getSessionFactory().addListener(applicationContext.getBean(EchoSessionListener.class)); return sshd; } diff --git a/src/main/java/com/example/sshd/core/EchoSessionListener.java b/src/main/java/com/example/sshd/core/EchoSessionListener.java new file mode 100644 index 0000000..7fd14ed --- /dev/null +++ b/src/main/java/com/example/sshd/core/EchoSessionListener.java @@ -0,0 +1,46 @@ +package com.example.sshd.core; + +import java.net.InetSocketAddress; +import java.util.Map; + +import org.apache.sshd.common.Session; +import org.apache.sshd.common.SessionListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class EchoSessionListener implements SessionListener { + + private static final Logger logger = LoggerFactory.getLogger(EchoSessionListener.class); + + @Autowired + Map remoteSessionMapping; + + @Override + public void sessionCreated(Session session) { + logger.info("sessionCreated: {}", session); + if (session.getIoSession().getRemoteAddress() instanceof InetSocketAddress) { + InetSocketAddress remoteAddress = (InetSocketAddress) session.getIoSession().getRemoteAddress(); + String remoteIpAddress = remoteAddress.getAddress().getHostAddress(); + if (remoteSessionMapping.containsKey(remoteIpAddress)) { + logger.info("kill old session: {} -> {}", remoteIpAddress, remoteSessionMapping.get(remoteIpAddress)); + remoteSessionMapping.get(remoteIpAddress).close(false); + } + logger.info("new session: {} -> {}", remoteIpAddress, session); + remoteSessionMapping.put(remoteIpAddress, session); + } + } + + @Override + public void sessionEvent(Session session, Event event) { + logger.info("sessionEvent: {}, event: {}", session, event); + } + + @Override + public void sessionClosed(Session session) { + logger.info("sessionCreated: {}", session); + } + +}