Flutter SSH连接插件dartssh3的使用

发布于 1周前 作者 wuwangju 来自 Flutter

Flutter SSH连接插件dartssh3的使用

简介

dartssh3 是一个用纯 Dart 编写的 SSH 和 SFTP 客户端库。它旨在功能丰富且易于使用,同时支持 Dart VM 和 Flutter 平台。

dartssh3 是对 dartssh2 的分支,因为原作者停止了开发。


✨ 特性

  • Pure Dart: 支持在 Dart VM 和 Flutter 中运行。
  • SSH Session: 支持执行命令、启动 shell、设置环境变量、伪终端等。
  • Authentication: 支持密码、私钥和交互式认证方法。
  • Forwarding: 支持本地转发和远程转发。
  • SFTP: 支持所有定义在 SFTPv3 协议 中的操作,包括上传、下载、列表、链接、删除、重命名等。

🧱 构建工具

以下是一些使用 dartssh3 构建的应用:

应用名称 描述
ServerBox 提供服务器管理和监控界面,支持通过 dartssh3 连接远程服务器。
ServerBox 的界面展示连接管理选项。
ServerBox 的用户界面,用于服务器控制和监控。
Ssh! No Ports 展示通过 dartssh3 实现无开放端口的 SSH 连接。
Ssh! No Ports 的演示,无需开放端口即可实现 SSH 连接。
DartShell 显示终端和会话信息以支持 SSH 操作。
DartShell 的终端界面展示。

欢迎通过 Pull Request 添加您的应用!


🧪 尝试

安装 dartssh 命令行工具:

# 安装 `dartssh` 命令。
dart pub global activate dartssh2_cli

# 使用 `dartssh` 像普通 `ssh` 命令一样。
dartssh user@example.com

# 示例:在远程主机上执行命令。
dartssh user@example.com ls -al

# 示例:连接到非标准端口。
dartssh user@example.com:<port>

# 使用 SFTP 传输文件。
dartsftp user@example.com

如果安装后无法找到 dartssh 命令,请确保设置好路径:设置路径指南


🚀 快速开始

连接到远程主机

final client = SSHClient(
  await SSHSocket.connect('localhost', 22),
  username: '<username>',
  onPasswordRequest: () => '<password>',
);

<code>SSHSocket</code> 是一个接口,您可以根据需要实现自定义的 <code>SSHSocket</code>,例如使用 WebSocket 或 Unix 域套接字作为底层传输。


启动远程主机上的 shell

final shell = await client.shell();
stdout.addStream(shell.stdout); // 监听标准输出
stderr.addStream(shell.stderr); // 监听错误输出
stdin.cast<Uint8List>().listen(shell.write); // 写入标准输入

await shell.done; // 等待 shell 退出
client.close();

在远程主机上执行命令

final uptime = await client.run('uptime');
print(utf8.decode(uptime));

忽略标准错误:

final uptime = await client.run('uptime', stderr: false);
print(utf8.decode(uptime));

<code>client.run()</code> 是一个便捷方法,用于包装 <code>client.execute()</code> 来运行非交互式命令。


在远程主机上启动进程

final session = await client.execute('cat > file.txt');
await session.stdin.addStream(File('local_file.txt').openRead().cast());
await session.stdin.close(); // 关闭流以发送 EOF 给远程进程。

await session.done; // 等待会话完成,确保所有数据都已刷新到远程进程。
print(session.exitCode); // 会话完成后可以获取退出码

推荐使用 <code>session.stdin.addStream()</code> 而不是 <code>session.write()</code>,特别是在传输大量数据时。


通过信号终止远程进程

session.kill(SSHSignal.KILL);
await session.done;
print('exitCode: ${session.exitCode}'); // -> exitCode: null
print('signal: ${session.exitSignal?.signalName}'); // -> signal: KILL

被信号终止的进程没有退出码,而是有退出信号属性。


本地端口转发(将本地端口 8080 转发到服务器)

final serverSocket = await ServerSocket.bind('localhost', 8080);
await for (final socket in serverSocket) {
  final forward = await client.forwardLocal('httpbin.org', 80);
  forward.stream.cast<List<int>>().pipe(socket);
  socket.pipe(forward.sink);
}

远程端口转发(将服务器的 2222 端口转发到本地 22 端口)

final forward = await client.forwardRemote(port: 2222);

if (forward == null) {
  print('Failed to forward remote port');
  return;
}

await for (final connection in forward.connections) {
  final socket = await Socket.connect('localhost', 22);
  connection.stream.cast<List<int>>().pipe(socket);
  socket.pipe(connection.sink);
}

使用公钥进行身份验证

final client = SSHClient(
  socket,
  username: '<username>',
  identities: [
    // 单个私钥文件可能包含多个密钥。
    ...SSHKeyPair.fromPem(await File('path/to/id_rsa').readAsString())
  ],
);

使用加密的 PEM 文件

// 测试私钥是否加密。
final encrypted = SSHKeyPair.isEncrypted(await File('path/to/id_rsa').readAsString());
print(encrypted);

// 如果私钥加密,则需要提供密码短语。
final keys = SSHKeyPair.fromPem('<pem text>', '<passphrase>');
print(keys);

在 Flutter 中解密 PEM 文件:

List<SSHKeyPair> decryptKeyPairs(List<String> args) {
  return SSHKeyPair.fromPem(args[0], args[1]);
}

final keypairs = await compute(decryptKeyPairs, ['<pem text>', '<passphrase>']);

获取 SSH 服务器版本

await client.authenticated;
print(client.remoteVersion); // SSH-2.0-OpenSSH_7.4p1

通过跳板机连接

final jumpServer = SSHClient(
  await SSHSocket.connect('<jump server>', 22),
  username: '...',
  onPasswordRequest: () => '...',
);

final client = SSHClient(
  await jumpServer.forwardLocal('<target server>', 22),
  username: '...',
  onPasswordRequest: () => '...',
);

print(utf8.decode(await client.run('hostname'))); // -> <target server> 的主机名

SFTP

列出远程目录

final sftp = await client.sftp();
final items = await sftp.listdir('/');
for (final item in items) {
  print(item.longname);
}

读取远程文件

final sftp = await client.sftp();
final file = await sftp.open('/etc/passwd');
final content = await file.readBytes();
print(latin1.decode(content));

写入远程文件

final sftp = await client.sftp();
final file = await sftp.open('file.txt', mode: SftpFileOpenMode.write);
await file.writeBytes(utf8.encode('hello there!') as Uint8List);

在特定偏移处写入数据

final data = utf8.encode('world') as Uint8List;
await file.writeBytes(data, offset: 6);

文件上传

final sftp = await client.sftp();
final file = await sftp.open('file.txt', mode: SftpFileOpenMode.create | SftpFileOpenMode.write);
await file.write(File('local_file.txt').openRead().cast());

暂停和恢复文件上传

final uploader = await file.write(File('local_file.txt').openRead().cast());
// ...
await uploader.pause();
// ...
await uploader.resume();
await uploader.done;

清空远程文件再打开

final file = await sftp.open('file.txt',
  mode: SftpFileOpenMode.create | SftpFileOpenMode.truncate | SftpFileOpenMode.write
);

目录操作

final sftp = await client.sftp();
await sftp.mkdir('/path/to/dir');
await sftp.rmdir('/path/to/dir');

获取/设置远程文件/目录的属性

await sftp.stat('/path/to/file');
await sftp.setStat(
  '/path/to/file',
  SftpFileAttrs(mode: SftpFileMode(userRead: true)),
);

获取远程文件类型

final stat = await sftp.stat('/path/to/file');
print(stat.type);
// 或者
print(stat.isDirectory);
print(stat.isSocket);
print(stat.isSymbolicLink);
// ...

创建链接

final sftp = await client.sftp();
sftp.link('/from', '/to');

获取远程文件系统总空间和可用空间

final sftp = await client.sftp();
final statvfs = await sftp.statvfs('/root');
print('total: ${statvfs.blockSize * statvfs.totalBlocks}');
print('free: ${statvfs.blockSize * statvfs.freeBlocks}');

示例代码

以下是完整的示例代码,展示如何使用 dartssh3 连接到远程主机并执行命令。

示例代码:SSH Client

import 'dart:convert';
import 'dart:io';

import 'package:dartssh3/dartssh3.dart';

void main(List<String> args) async {
  // 连接到远程主机
  final socket = await SSHSocket.connect('localhost', 22);

  final client = SSHClient(
    socket,
    username: 'root',
    onPasswordRequest: () {
      stdout.write('Password: ');
      stdin.echoMode = false;
      return stdin.readLineSync() ?? exit(1);
    },
  );

  // 执行命令并打印结果
  final uptime = await client.run('uptime');
  print(utf8.decode(uptime));

  // 关闭客户端
  client.close();
  await client.done;
}

更多关于Flutter SSH连接插件dartssh3的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter SSH连接插件dartssh3的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


dartssh3 是一个用于在 Flutter 应用中实现 SSH 连接的插件。它基于 dartssh 库,提供了 SSH 客户端功能,允许你在 Flutter 应用中执行远程命令、传输文件等操作。

以下是如何在 Flutter 项目中使用 dartssh3 插件的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 dartssh3 依赖:

dependencies:
  flutter:
    sdk: flutter
  dartssh3: ^0.0.1  # 请检查最新版本

然后运行 flutter pub get 来安装依赖。

2. 导入库

在你的 Dart 文件中导入 dartssh3 库:

import 'package:dartssh3/dartssh3.dart';

3. 创建 SSH 连接

使用 SSHClient 类来创建 SSH 连接。你需要提供远程主机的地址、端口、用户名和密码(或私钥)。

void connectToSSH() async {
  final client = SSHClient(
    host: 'your.remote.host',
    port: 22,
    username: 'your_username',
    passwordOrKey: 'your_password', // 或者使用私钥
  );

  try {
    await client.connect();
    print('Connected to SSH server');

    // 执行远程命令
    final result = await client.execute('ls -la');
    print('Command result: $result');

    // 关闭连接
    await client.disconnect();
    print('Disconnected from SSH server');
  } catch (e) {
    print('Failed to connect: $e');
  }
}

4. 执行远程命令

使用 execute 方法可以在远程服务器上执行命令,并获取命令的输出。

final result = await client.execute('ls -la');
print('Command result: $result');

5. 文件传输

dartssh3 也支持文件传输。你可以使用 scp 方法来上传或下载文件。

// 上传文件
await client.scpUpload('local_file.txt', 'remote_file.txt');

// 下载文件
await client.scpDownload('remote_file.txt', 'local_file.txt');

6. 关闭连接

完成操作后,记得关闭 SSH 连接。

await client.disconnect();

7. 处理异常

在实际使用中,可能会遇到各种异常情况,如连接失败、认证失败等。确保在代码中处理这些异常。

try {
  await client.connect();
  // 其他操作
} catch (e) {
  print('Error: $e');
} finally {
  await client.disconnect();
}

8. 使用私钥认证

如果你使用私钥进行认证,可以将私钥文件的内容传递给 passwordOrKey 参数。

final client = SSHClient(
  host: 'your.remote.host',
  port: 22,
  username: 'your_username',
  passwordOrKey: '-----BEGIN RSA PRIVATE KEY-----\n...', // 私钥内容
);

9. 完整示例

以下是一个完整的示例,展示了如何使用 dartssh3 进行 SSH 连接、执行命令和文件传输。

import 'package:dartssh3/dartssh3.dart';

void main() async {
  final client = SSHClient(
    host: 'your.remote.host',
    port: 22,
    username: 'your_username',
    passwordOrKey: 'your_password', // 或者使用私钥
  );

  try {
    await client.connect();
    print('Connected to SSH server');

    // 执行远程命令
    final result = await client.execute('ls -la');
    print('Command result: $result');

    // 上传文件
    await client.scpUpload('local_file.txt', 'remote_file.txt');
    print('File uploaded');

    // 下载文件
    await client.scpDownload('remote_file.txt', 'local_file.txt');
    print('File downloaded');

    // 关闭连接
    await client.disconnect();
    print('Disconnected from SSH server');
  } catch (e) {
    print('Error: $e');
  } finally {
    await client.disconnect();
  }
}
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!