开发者社区 > 博文 > java免密连接SSH
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

java免密连接SSH

  • 京东城市JUST团队
  • 2021-01-22
  • IP归属:未知
  • 51360浏览

本文使用2个java库示例如何免密连接ssh执行命令。

JSch

http://www.jcraft.com/

        <!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>

主要逻辑很简单,可以通过密码和密钥的形式:

        final JSch sch = new JSch();
        // 密钥方式
        sch.setKnownHosts("~/.ssh/known_hosts");
        sch.addIdentity("~/.ssh/id_rsa", "~/.ssh/id_rsa.pub", null);

        final Session session = sch.getSession("test", "10.10.10.111");
        // 密码方式
        // session.setPassword("password");
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();

        final Channel sftp = session.openChannel("sftp");
        sftp.connect();
        session.disconnect();

Apache mina sshd

https://github.com/apache/mina-sshd

        <dependency>
            <groupId>org.apache.sshd</groupId>
            <artifactId>sshd-core</artifactId>
            <version>2.5.0</version>
            <optional>true</optional>
        </dependency>

参考jenkins实现

    public static void main(String[] args) throws IOException {
        final String pk = readPemFile(new File("/home/test/.ssh/id_rsa"));
        sshConnection("10.10.10.111", 22, "test", false, pk);
    }

    /**
     * 读取文件内容
     */
    public static String readPemFile(File f) throws IOException {
        try (InputStream is = Files.newInputStream(f.toPath());
             DataInputStream dis = new DataInputStream(is)) {
            byte[] bytes = new byte[(int) f.length()];
            dis.readFully(bytes);
            return new String(bytes);
        } catch (InvalidPathException e) {
            throw new IOException(e);
        }
    }

    /**
     * 获取密钥对
     */
    static KeyPair getKeyPairFromString(String pk) throws IOException, NoSuchAlgorithmException {
        final KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
        final KeyPair keyPair = rsa.generateKeyPair();
        final ByteArrayOutputStream stream = new ByteArrayOutputStream();
        stream.write(pk.getBytes());
        final ObjectOutputStream o = new ObjectOutputStream(stream);
        o.writeObject(keyPair);
        return keyPair;
    }

    /**
     * SSH连接
     */
    private static int sshConnection(String host, int port, String user,
                                     final boolean strictHostKey, String privateKey) throws IOException {
        try (SshClient client = SshClient.setUpDefaultClient()) {

            KnownHostsServerKeyVerifier verifier = new DefaultKnownHostsServerKeyVerifier(new ServerKeyVerifier() {
                @Override
                public boolean verifyServerKey(ClientSession clientSession, SocketAddress remoteAddress,
                                               PublicKey serverKey) {
                    return !strictHostKey;
                }
            }, true);

            client.setServerKeyVerifier(verifier);
            client.start();

            ConnectFuture cf = client.connect(user, host, port);
            cf.await();
            try (ClientSession session = cf.getSession()) {
                // 这里可以加多个
//                for (KeyPair pair : provider.getKeys()) {
//                    session.addPublicKeyIdentity(pair);
//                }
                // 只要主机配了免密,这里不加也可以
                session.addPublicKeyIdentity(getKeyPairFromString(privateKey));
                session.auth().verify(10000L);

                // 这里命令可以传进来
                try (ClientChannel channel = session.createExecChannel("ls /")) {
                    channel.setIn(new NoCloseInputStream(System.in));
                    channel.setOut(new NoCloseOutputStream(System.out));
                    channel.setErr(new NoCloseOutputStream(System.err));
                    WaitableFuture wf = channel.open();
                    wf.await();

                    Set<ClientChannelEvent> waitMask =
                            channel.waitFor(Collections.singletonList(ClientChannelEvent.CLOSED), 0L);

                    if (waitMask.contains(ClientChannelEvent.TIMEOUT)) {
                        System.err.println("超时");
                    }
                    return channel.getExitStatus();
                }
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } finally {
                client.stop();
            }
        }
        return 0;
    }
共0条评论