ZetCode

Dart RawSecureSocket

最后修改于 2025 年 4 月 4 日

Dart 中的 `RawSecureSocket` 类使用 SSL/TLS 协议提供安全套接字通信。它对于客户端-服务器应用程序中的加密网络通信至关重要。

RawSecureSocket 扩展了 RawSocket,并增加了诸如加密、证书验证和安全握手等安全功能。它是 Dart `dart:io` 库的一部分,用于非 Web 应用程序。

基本定义

RawSecureSocket 是安全套接字通信的低级接口。它在提供原始字节访问的同时处理 SSL/TLS 加密。

主要功能包括安全连接建立、证书管理和加密数据传输。它可与客户端和服务器套接字配合使用。

基本安全客户端连接

此示例演示了如何建立基本安全客户端连接。

main.dart
import 'dart:io';

Future<void> main() async {
  try {
    var socket = await RawSecureSocket.connect('example.com', 443);
    print('Connected to ${socket.address.address}:${socket.port}');
    
    socket.writeEventsEnabled = true;
    socket.write(Uint8List.fromList('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'.codeUnits));
    
    socket.listen((event) {
      if (event == RawSocketEvent.read) {
        print(String.fromCharCodes(socket.read()));
      }
    });
  } catch (e) {
    print('Connection failed: $e');
  }
}

我们在端口 443(HTTPS)上连接到 example.com。连接后,我们发送一个 HTTP 请求并监听响应。套接字会自动处理所有加密。

$ dart main.dart
Connected to 93.184.216.34:443
HTTP/1.1 200 OK
...

服务器证书验证

此示例演示了自定义证书验证。

main.dart
import 'dart:io';

Future<void> main() async {
  var context = SecurityContext.defaultContext;
  context.setTrustedCertificates('path/to/cert.pem');
  
  try {
    var socket = await RawSecureSocket.connect(
      'example.com',
      443,
      context: context,
      onBadCertificate: (cert) {
        print('Bad certificate: ${cert.subject}');
        return false; // Reject invalid certificates
      }
    );
    
    print('Connected with verified certificate');
    socket.close();
  } catch (e) {
    print('Connection failed: $e');
  }
}

我们创建一个带有自定义受信任证书的 SecurityContext。onBadCertificate 回调允许处理证书验证错误。这对于安全敏感的应用程序至关重要。

$ dart main.dart
Connected with verified certificate

安全服务器实现

此示例演示了基本的安全服务器实现。

main.dart
import 'dart:io';

Future<void> main() async {
  var context = SecurityContext()
    ..useCertificateChain('server.crt')
    ..usePrivateKey('server.key');
  
  var server = await SecureServerSocket.bind(
    'localhost',
    8443,
    context,
    backlog: 5
  );
  
  print('Secure server listening on ${server.address.address}:${server.port}');
  
  server.listen((client) {
    client.write('Hello secure client!\n');
    client.close();
  });
}

我们使用证书和私钥文件创建了一个安全服务器。服务器监听传入的连接并用一个简单消息进行响应。所有通信都会自动加密。

$ dart main.dart
Secure server listening on 127.0.0.1:8443

客户端身份验证

此示例演示了双向 TLS 身份验证。

main.dart
import 'dart:io';

Future<void> main() async {
  var serverContext = SecurityContext()
    ..useCertificateChain('server.crt')
    ..usePrivateKey('server.key')
    ..setClientAuthorities('ca.crt')
    ..requestClientCertificate(true);
  
  var server = await SecureServerSocket.bind(
    'localhost',
    8443,
    serverContext
  );
  
  server.listen((client) {
    var cert = client.peerCertificate;
    if (cert != null) {
      print('Client authenticated: ${cert.subject}');
    }
    client.close();
  });
  
  // Client with certificate
  var clientContext = SecurityContext()
    ..useCertificateChain('client.crt')
    ..usePrivateKey('client.key')
    ..setTrustedCertificates('ca.crt');
  
  var socket = await RawSecureSocket.connect(
    'localhost',
    8443,
    context: clientContext
  );
  
  socket.close();
  server.close();
}

服务器需要客户端证书进行身份验证。客户端在握手期间提供其证书。这实现了双向 TLS 身份验证。

$ dart main.dart
Client authenticated: CN=client

处理安全套接字事件

此示例演示了全面的事件处理。

main.dart
import 'dart:io';

Future<void> main() async {
  var socket = await RawSecureSocket.connect('example.com', 443);
  
  socket.listen((event) {
    switch (event) {
      case RawSocketEvent.read:
        var data = socket.read();
        print('Received: ${data?.length} bytes');
        break;
      case RawSocketEvent.write:
        print('Ready to write');
        break;
      case RawSocketEvent.readClosed:
        print('Read closed');
        break;
      case RawSocketEvent.closed:
        print('Connection closed');
        break;
    }
  }, onError: (e) {
    print('Error: $e');
  }, onDone: () {
    print('Done');
  });
  
  socket.writeEventsEnabled = true;
  socket.write(Uint8List.fromList('PING'.codeUnits));
  
  await Future.delayed(Duration(seconds: 2));
  socket.close();
}

我们处理各种套接字事件,包括数据接收、写入就绪和连接关闭。基于事件的 API 允许高效地处理异步套接字操作。

$ dart main.dart
Ready to write
Received: 142 bytes
Connection closed
Done

最佳实践

来源

Dart RawSecureSocket 文档

本教程涵盖了 Dart 的 RawSecureSocket 类,并通过实际示例展示了安全通信、证书处理和事件管理。

作者

我叫 Jan Bodnar,是一名热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出 所有 Dart 教程