Skip to content

Commit

Permalink
upgrade ssh dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
githubname1024 committed Feb 28, 2024
1 parent 96ee181 commit aa7fcc1
Show file tree
Hide file tree
Showing 11 changed files with 766 additions and 572 deletions.
11 changes: 7 additions & 4 deletions cachecloud-web/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,17 @@
<scope>provided</scope>
</dependency>

<!-- ssh -->
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>${ssh-version}</version>
</dependency>

<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>sshj</artifactId>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-scp</artifactId>
<version>${ssh-version}</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.sohu.cache.configuration;

import com.sohu.cache.ssh.SSHSessionPooledObjectFactory;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.apache.sshd.client.session.ClientSession;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.security.GeneralSecurityException;

/**
* @Author: zengyizhao
* @CreateTime: 2024/2/22 15:20
* @Description: ssh session 连接池配置
* @Version: 1.0
*/
@Configuration
public class SSHPoolConfig {

/**
* ssh连接池配置
* @return
*/
@Bean
public GenericKeyedObjectPool<String, ClientSession> clientSessionPool() throws GeneralSecurityException, IOException {
GenericKeyedObjectPoolConfig genericKeyedObjectPoolConfig = new GenericKeyedObjectPoolConfig();
genericKeyedObjectPoolConfig.setTestWhileIdle(true);
genericKeyedObjectPoolConfig.setTestOnReturn(true);
genericKeyedObjectPoolConfig.setMaxTotalPerKey(5);
genericKeyedObjectPoolConfig.setMaxIdlePerKey(1);
genericKeyedObjectPoolConfig.setMinIdlePerKey(1);
genericKeyedObjectPoolConfig.setMaxWaitMillis(30000);
genericKeyedObjectPoolConfig.setTimeBetweenEvictionRunsMillis(20000);
genericKeyedObjectPoolConfig.setJmxEnabled(false);
SSHSessionPooledObjectFactory factory = new SSHSessionPooledObjectFactory();
GenericKeyedObjectPool<String, ClientSession> genericKeyedObjectPool = new GenericKeyedObjectPool<>(
factory,
genericKeyedObjectPoolConfig);
return genericKeyedObjectPool;
}
}
84 changes: 84 additions & 0 deletions cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.sohu.cache.ssh;

import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.auth.password.PasswordIdentityProvider;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.config.keys.loader.KeyPairResourceLoader;
import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.util.security.SecurityUtils;

import java.io.IOException;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
* ssh client
*
* @Auther: yongfeigao
* @Date: 2023/10/23
*/
@Data
public class SSHClient {

// 服务器 ssh 用户
private String serverUser;

// 服务器 ssh 密码
private String serverPassword;

// 服务器 ssh 端口
private Integer serverPort;

// 服务器 ssh 链接建立超时时间
private Integer serverConnectTimeout;

// 服务器 ssh 操作超时时间
private Integer serverOPTimeout;

// 服务器 ssh 私钥
private String privateKeyPath;

private SshClient client;

public void init() throws GeneralSecurityException, IOException {
client = buildSshClient();
if (StringUtils.isNotEmpty(privateKeyPath)) {
setAuthByKey(client);
}
client.setPasswordIdentityProvider(PasswordIdentityProvider.wrapPasswords(getServerPassword()));
client.start();
}

private SshClient buildSshClient() {
SshClient client = SshClient.setUpDefaultClient();
client.setSessionHeartbeat(Session.HeartbeatType.IGNORE, TimeUnit.SECONDS, 10);
return client;
}

private void setAuthByKey(SshClient client) throws GeneralSecurityException, IOException {
KeyPairResourceLoader loader = SecurityUtils.getKeyPairResourceParser();

Collection<KeyPair> keys = loader.loadKeyPairs(null, Paths.get(privateKeyPath), null);
client.setKeyIdentityProvider(KeyIdentityProvider.wrapKeyPairs(keys));
}

/**
* 连接服务器
*
* @param ip
* @return
* @throws IOException
*/
public ClientSession connect(String ip) throws IOException {
ClientSession session = getClient().connect(getServerUser(), ip, getServerPort()).verify(getServerConnectTimeout(), TimeUnit.MILLISECONDS).getSession();
session.auth().verify(getServerConnectTimeout(), TimeUnit.MILLISECONDS);
return session;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public interface SSHService {
* @return
* @throws SSHException
*/
SSHTemplate.Result executeWithResult(String ip, int port, String username, String password, final String command,int timeoutMills) throws SSHException;
SSHTemplate.Result executeWithResult(String ip, int port, String username, String password, final String command, int timeoutMills) throws SSHException;

/**
* 拷贝文件到远程目录
Expand All @@ -57,7 +57,7 @@ public interface SSHService {
* @throws SSHException
*/
SSHTemplate.Result scpFileToRemote(String ip, int port, String username,
String password, final String localPath, final String remoteDir) throws SSHException;
String password, final String localPath, final String remoteDir) throws SSHException;

/**
* 拷贝文件到远程目录
Expand Down Expand Up @@ -94,7 +94,7 @@ SSHTemplate.Result scpFileToRemote(String ip, int port, String username,
* @return
* @throws SSHException
*/
SSHTemplate.Result executeWithResult(String ip, String cmd,int millsSecond) throws SSHException;
SSHTemplate.Result executeWithResult(String ip, String cmd, int millsSecond) throws SSHException;

/**
* 查看机器ip上的端口port是否已被占用;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.sohu.cache.ssh;

import com.sohu.cache.util.ConstUtils;
import com.sohu.cache.web.enums.SshAuthTypeEnum;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.sshd.client.session.ClientSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.concurrent.TimeUnit;

/**
* ssh session链接池工厂
*
* @Auther: yongfeigao
* @Date: 2023/10/20
*/
public class SSHSessionPooledObjectFactory implements KeyedPooledObjectFactory<String, ClientSession> {

private final Logger logger = LoggerFactory.getLogger(getClass());

private SSHClient sshClient;

public SSHSessionPooledObjectFactory() throws GeneralSecurityException, IOException {
sshClient = new SSHClient();
sshClient.setServerUser(ConstUtils.USERNAME);
sshClient.setServerPassword(ConstUtils.PASSWORD);
sshClient.setServerPort(ConstUtils.SSH_PORT_DEFAULT);
sshClient.setServerConnectTimeout(ConstUtils.SSH_CONNECTION_TIMEOUT);
if (ConstUtils.SSH_AUTH_TYPE == SshAuthTypeEnum.PUBLIC_KEY.getValue()) {
sshClient.setPrivateKeyPath(ConstUtils.PUBLIC_KEY_PEM);
}
sshClient.init();
}

@Override
public PooledObject<ClientSession> makeObject(String ip) throws Exception {
int port = ConstUtils.SSH_PORT_DEFAULT;
ClientSession session = sshClient.getClient().connect(ConstUtils.USERNAME, ip,
port).verify(ConstUtils.SSH_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS).getSession();
session.auth().verify(ConstUtils.SSH_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS);
logger.info("create object, key:{}", ip);
return new DefaultPooledObject<>(session);
}

@Override
public void destroyObject(String ip, PooledObject<ClientSession> pooledObject) throws Exception {
ClientSession clientSession = pooledObject.getObject();
if (clientSession != null) {
try {
clientSession.close();
} catch (Exception e) {
logger.warn("close err, key:{}", ip, e);
}
}
logger.info("destroy object {}", ip);
}

@Override
public boolean validateObject(String ip, PooledObject<ClientSession> pooledObject) {
boolean closed = pooledObject.getObject().isClosed();
if (closed) {
logger.warn("{} session closed", ip);
return false;
}
return true;
}

@Override
public void activateObject(String ip, PooledObject<ClientSession> pooledObject) throws Exception {

}

@Override
public void passivateObject(String ip, PooledObject<ClientSession> pooledObject) throws Exception {

}
}
Loading

0 comments on commit aa7fcc1

Please sign in to comment.