mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-24 18:04:54 +08:00
fix code
This commit is contained in:
parent
b865d8b728
commit
7f709f2730
@ -13,8 +13,10 @@
|
||||
package org.dromara.hutool.extra.ssh;
|
||||
|
||||
import org.dromara.hutool.core.func.Wrapper;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* SSH Session抽象
|
||||
@ -29,4 +31,47 @@ public interface Session extends Wrapper<Object>, Closeable {
|
||||
* @return 是否连接状态
|
||||
*/
|
||||
boolean isConnected();
|
||||
|
||||
// region bindPort
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口<br>
|
||||
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort<br>
|
||||
* 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等
|
||||
*
|
||||
* @param localPort 本地端口
|
||||
* @param remoteAddress 远程主机和端口
|
||||
* @return 成功与否
|
||||
*/
|
||||
default boolean bindLocalPort(final int localPort, final InetSocketAddress remoteAddress) {
|
||||
return bindLocalPort(new InetSocketAddress(localPort), remoteAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口<br>
|
||||
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort<br>
|
||||
* 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等
|
||||
*
|
||||
* @param localAddress 本地主机和端口
|
||||
* @param remoteAddress 远程主机和端口
|
||||
* @return 成功与否
|
||||
*/
|
||||
boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress);
|
||||
|
||||
/**
|
||||
* 解除本地端口映射
|
||||
*
|
||||
* @param localPort 需要解除的本地端口
|
||||
* @throws IORuntimeException 端口解绑失败异常
|
||||
*/
|
||||
default void unBindLocalPort(final int localPort){
|
||||
unBindLocalPort(new InetSocketAddress(localPort));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除本地端口映射
|
||||
*
|
||||
* @param localAddress 需要解除的本地地址
|
||||
*/
|
||||
void unBindLocalPort(final InetSocketAddress localAddress);
|
||||
// endregion
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class GanymedSession implements Session {
|
||||
private Connection connection;
|
||||
private final ch.ethz.ssh2.Session raw;
|
||||
|
||||
private Map<Integer, LocalPortForwarder> localPortForwarderMap;
|
||||
private Map<String, LocalPortForwarder> localPortForwarderMap;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -91,37 +91,11 @@ public class GanymedSession implements Session {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口<br>
|
||||
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort<br>
|
||||
* 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等
|
||||
*
|
||||
* @param remoteHost 远程主机
|
||||
* @param remotePort 远程端口
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws IORuntimeException 端口绑定失败异常
|
||||
*/
|
||||
public boolean bindLocalPort(final String remoteHost, final int remotePort, final int localPort) throws IORuntimeException {
|
||||
return bindLocalPort(remoteHost, remotePort, Ipv4Util.LOCAL_IP, localPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口<br>
|
||||
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort<br>
|
||||
* 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等
|
||||
*
|
||||
* @param remoteHost 远程主机
|
||||
* @param remotePort 远程端口
|
||||
* @param localHost 本地主机
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws IORuntimeException 端口绑定失败异常
|
||||
*/
|
||||
public boolean bindLocalPort(final String remoteHost, final int remotePort, final String localHost, final int localPort) throws IORuntimeException {
|
||||
@Override
|
||||
public boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException {
|
||||
final LocalPortForwarder localPortForwarder;
|
||||
try {
|
||||
localPortForwarder = this.connection.createLocalPortForwarder(new InetSocketAddress(localHost, localPort), remoteHost, remotePort);
|
||||
localPortForwarder = this.connection.createLocalPortForwarder(localAddress, remoteAddress.getHostName(), remoteAddress.getPort());
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
@ -131,23 +105,18 @@ public class GanymedSession implements Session {
|
||||
}
|
||||
|
||||
//加入记录
|
||||
this.localPortForwarderMap.put(localPort, localPortForwarder);
|
||||
this.localPortForwarderMap.put(localAddress.toString(), localPortForwarder);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除本地端口映射
|
||||
*
|
||||
* @param localPort 需要解除的本地端口
|
||||
* @throws IORuntimeException 端口解绑失败异常
|
||||
*/
|
||||
public void unBindLocalPort(final int localPort) throws IORuntimeException {
|
||||
@Override
|
||||
public void unBindLocalPort(final InetSocketAddress localAddress) throws IORuntimeException {
|
||||
if (MapUtil.isEmpty(this.localPortForwarderMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final LocalPortForwarder localPortForwarder = this.localPortForwarderMap.remove(localPort);
|
||||
final LocalPortForwarder localPortForwarder = this.localPortForwarderMap.remove(localAddress.toString());
|
||||
if (null != localPortForwarder) {
|
||||
try {
|
||||
localPortForwarder.close();
|
||||
|
@ -12,10 +12,12 @@
|
||||
|
||||
package org.dromara.hutool.extra.ssh.engine.jsch;
|
||||
|
||||
import com.jcraft.jsch.*;
|
||||
import com.jcraft.jsch.Channel;
|
||||
import com.jcraft.jsch.ChannelExec;
|
||||
import com.jcraft.jsch.ChannelShell;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.net.Ipv4Util;
|
||||
import org.dromara.hutool.core.util.ByteUtil;
|
||||
import org.dromara.hutool.core.util.CharsetUtil;
|
||||
import org.dromara.hutool.extra.ssh.Connector;
|
||||
@ -25,6 +27,7 @@ import org.dromara.hutool.extra.ssh.SshException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
@ -70,53 +73,23 @@ public class JschSession implements Session {
|
||||
JschUtil.close(this.raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口<br>
|
||||
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort<br>
|
||||
* 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等
|
||||
*
|
||||
* @param remoteHost 远程主机
|
||||
* @param remotePort 远程端口
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws SshException 端口绑定失败异常
|
||||
*/
|
||||
public boolean bindLocalPort(final String remoteHost, final int remotePort, final int localPort) throws SshException {
|
||||
return bindLocalPort(remoteHost, remotePort, Ipv4Util.LOCAL_IP, localPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口<br>
|
||||
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort<br>
|
||||
* 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等
|
||||
*
|
||||
* @param remoteHost 远程主机
|
||||
* @param remotePort 远程端口
|
||||
* @param localHost 本地主机
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws SshException 端口绑定失败异常
|
||||
*/
|
||||
public boolean bindLocalPort(final String remoteHost, final int remotePort, final String localHost, final int localPort) throws SshException {
|
||||
@Override
|
||||
public boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws SshException {
|
||||
if (isConnected()) {
|
||||
try {
|
||||
this.raw.setPortForwardingL(localHost, localPort, remoteHost, remotePort);
|
||||
this.raw.setPortForwardingL(localAddress.getHostName(), localAddress.getPort(), remoteAddress.getHostName(), remoteAddress.getPort());
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e, "From [{}:{}] mapping to [{}:{}] error!", remoteHost, remotePort, localHost, localPort);
|
||||
throw new SshException(e, "From [{}] mapping to [{}] error!", localAddress, remoteAddress);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除远程端口映射
|
||||
*
|
||||
* @param localPort 需要解除的本地端口
|
||||
*/
|
||||
public void unBindLocalPort(final int localPort) {
|
||||
@Override
|
||||
public void unBindLocalPort(final InetSocketAddress localAddress) {
|
||||
try {
|
||||
this.raw.delPortForwardingL(localPort);
|
||||
this.raw.delPortForwardingL(localAddress.getHostName(), localAddress.getPort());
|
||||
} catch (final JSchException e) {
|
||||
throw new SshException(e);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ package org.dromara.hutool.extra.ssh.engine.mina;
|
||||
import org.apache.sshd.client.SshClient;
|
||||
import org.apache.sshd.client.channel.ChannelShell;
|
||||
import org.apache.sshd.client.session.ClientSession;
|
||||
import org.apache.sshd.common.util.net.SshdSocketAddress;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.extra.ssh.Connector;
|
||||
@ -22,6 +23,7 @@ import org.dromara.hutool.extra.ssh.Session;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
@ -63,6 +65,25 @@ public class MinaSession implements Session {
|
||||
IoUtil.closeQuietly(this.sshClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException {
|
||||
try {
|
||||
this.raw.startLocalPortForwarding(new SshdSocketAddress(localAddress), new SshdSocketAddress(remoteAddress));
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unBindLocalPort(final InetSocketAddress localAddress) throws IORuntimeException {
|
||||
try {
|
||||
this.raw.stopLocalPortForwarding(new SshdSocketAddress(localAddress));
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行Shell命令
|
||||
*
|
||||
@ -100,16 +121,16 @@ public class MinaSession implements Session {
|
||||
* 此方法单次发送一个命令到服务端,自动读取环境变量,执行结束后自动关闭channel,不会产生阻塞。
|
||||
* </p>
|
||||
*
|
||||
* @param cmd 命令
|
||||
* @param charset 发送和读取内容的编码
|
||||
* @param cmd 命令
|
||||
* @param charset 发送和读取内容的编码
|
||||
* @param errStream 异常输出位置
|
||||
* @return 结果
|
||||
*/
|
||||
public String execByShell(final String cmd, final Charset charset, final OutputStream errStream){
|
||||
public String execByShell(final String cmd, final Charset charset, final OutputStream errStream) {
|
||||
final ChannelShell shellChannel;
|
||||
try {
|
||||
shellChannel = this.raw.createShellChannel();
|
||||
if(null != errStream){
|
||||
if (null != errStream) {
|
||||
shellChannel.setErr(errStream);
|
||||
}
|
||||
shellChannel.open().verify();
|
||||
@ -118,6 +139,6 @@ public class MinaSession implements Session {
|
||||
}
|
||||
|
||||
IoUtil.write(shellChannel.getInvertedIn(), charset, false, cmd);
|
||||
return IoUtil.read(shellChannel.getInvertedOut(),charset);
|
||||
return IoUtil.read(shellChannel.getInvertedOut(), charset);
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,9 @@ import net.schmizz.sshj.connection.channel.forwarded.SocketForwardingConnectList
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.net.Ipv4Util;
|
||||
import org.dromara.hutool.core.util.CharsetUtil;
|
||||
import org.dromara.hutool.extra.ssh.Connector;
|
||||
import org.dromara.hutool.extra.ssh.Session;
|
||||
import org.dromara.hutool.extra.ssh.SshException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@ -44,7 +42,7 @@ public class SshjSession implements Session {
|
||||
private SSHClient ssh;
|
||||
private final net.schmizz.sshj.connection.channel.direct.Session raw;
|
||||
|
||||
private Map<Integer, ServerSocket> localPortForwarderMap;
|
||||
private Map<String, ServerSocket> localPortForwarderMap;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -95,40 +93,16 @@ public class SshjSession implements Session {
|
||||
return new SshjSftp(this.ssh, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口<br>
|
||||
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort<br>
|
||||
* 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等
|
||||
*
|
||||
* @param remoteHost 远程主机
|
||||
* @param remotePort 远程端口
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws SshException 端口绑定失败异常
|
||||
*/
|
||||
public boolean bindLocalPort(final String remoteHost, final int remotePort, final int localPort) throws SshException {
|
||||
return bindLocalPort(remoteHost, remotePort, Ipv4Util.LOCAL_IP, localPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定端口到本地。 一个会话可绑定多个端口<br>
|
||||
* 当请求localHost:localPort时,通过SSH到服务器,转发请求到remoteHost:remotePort<br>
|
||||
* 此方法用于访问本地无法访问但是服务器可以访问的地址,如内网数据库库等
|
||||
*
|
||||
* @param remoteHost 远程主机
|
||||
* @param remotePort 远程端口
|
||||
* @param localHost 本地主机
|
||||
* @param localPort 本地端口
|
||||
* @return 成功与否
|
||||
* @throws IORuntimeException 端口绑定失败异常
|
||||
*/
|
||||
public boolean bindLocalPort(final String remoteHost, final int remotePort, final String localHost, final int localPort) throws IORuntimeException {
|
||||
final Parameters params = new Parameters(localHost, localPort, remoteHost, remotePort);
|
||||
@Override
|
||||
public boolean bindLocalPort(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IORuntimeException {
|
||||
final Parameters params = new Parameters(
|
||||
localAddress.getHostName(), localAddress.getPort(),
|
||||
remoteAddress.getHostName(), remoteAddress.getPort());
|
||||
final ServerSocket ss;
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.setReuseAddress(true);
|
||||
ss.bind(new InetSocketAddress(params.getLocalHost(), params.getLocalPort()));
|
||||
ss.bind(localAddress);
|
||||
ssh.newLocalPortForwarder(params, ss).listen();
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
@ -139,23 +113,18 @@ public class SshjSession implements Session {
|
||||
}
|
||||
|
||||
//加入记录
|
||||
this.localPortForwarderMap.put(localPort, ss);
|
||||
this.localPortForwarderMap.put(localAddress.toString(), ss);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除本地端口映射
|
||||
*
|
||||
* @param localPort 需要解除的本地端口
|
||||
* @throws IORuntimeException 端口解绑失败异常
|
||||
*/
|
||||
public void unBindLocalPort(final int localPort) throws IORuntimeException {
|
||||
@Override
|
||||
public void unBindLocalPort(final InetSocketAddress localAddress) throws IORuntimeException {
|
||||
if (MapUtil.isEmpty(this.localPortForwarderMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IoUtil.closeQuietly(this.localPortForwarderMap.remove(localPort));
|
||||
IoUtil.closeQuietly(this.localPortForwarderMap.remove(localAddress.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,6 +21,8 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* Jsch工具类单元测试
|
||||
*
|
||||
@ -36,7 +38,7 @@ public class JschTest {
|
||||
//新建会话,此会话用于ssh连接到跳板机(堡垒机),此处为10.1.1.1:22
|
||||
final JschSession session = new JschSession(new Connector("looly.centos", 22, "test", "123456"));
|
||||
// 将堡垒机保护的内网8080端口映射到localhost,我们就可以通过访问http://localhost:8080/访问内网服务了
|
||||
session.bindLocalPort("172.20.12.123", 8080, 8080);
|
||||
session.bindLocalPort(8080, new InetSocketAddress("172.20.12.123", 8080));
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
|
Loading…
Reference in New Issue
Block a user