Flutter ACME客户端插件ls_acme_client的使用

Flutter ACME客户端插件ls_acme_client的使用

Dart Acme Client

一个基于RFC 8555的ACME V2兼容客户端,用Dart语言编写。


目录

  1. 前言
  2. 安装
  3. 导入
  4. Acme客户端
  5. 申请证书颁发
  6. 更新日志
  7. 版权与许可

前言

由于此包是纯Dart编写的,因此可以在所有支持Dart的平台上运行。这包括像Flutter、Angular Dart等框架的使用。此外,该包也可以用于通过dart2native编译的命令行工具或REST服务。

注意: 如果发现错误、有疑问或功能请求,请随时创建拉取请求或提交问题。


安装

pubspec.yaml文件中添加以下依赖项:

dependencies:
  ls_acme_client: ^1.1.0

导入

通过以下方式导入包:

import 'package:ls_acme_client/acme_client.dart';

Acme客户端

这是一个基于RFC 8555的简单ACME客户端,能够与任何基于该RFC的ACME服务器通信,包括Let’s Encrypt。

客户端设置

通过调用构造函数并传递适当的参数来创建新客户端:

// 创建一个新的Acme客户端实例
var client = AcmeClient(
  'https://acme-server.com', // ACME服务器的基地址
  privateKeyPem,             // 私钥(PEM格式)
  publicKeyPem,              // 公钥(PEM格式)
  true,                      // 是否接受条款
  ['mailto:jon@doe.com'],    // 联系邮箱列表
);

// 初始化客户端,从服务器获取目录和账户信息
await client.init();

说明:

  • baseUrl: ACME服务器的基地址。
  • privateKeyPem: PEM格式的私钥。
  • publicKeyPem: PEM格式的公钥。
  • acceptTerms: 是否接受条款。
  • contacts: 邮箱地址列表,格式为'mailto:xxx@yyy.com'

提示: 如果需要生成RSA/ECC密钥对,可以查看Basic Utils包,其中包含生成密钥对和将其格式化为PEM所需的工具。


申请证书颁发

下单

通过创建新的Order对象并添加要放入证书中的标识符来下单:

// 创建订单对象
var order = Order(
  identifiers: [
    Identifiers(type: 'dns', value: 'example.com') // 添加DNS标识符
  ]
);

// 向ACME服务器提交订单
var newOrder = await client.order(order);

获取授权数据

通过调用getAuthorization()方法获取每个订单的授权数据:

// 获取授权数据
var auth = await client.getAuthorization(newOrder!);

// 遍历授权数据
for (var a in auth) {
  print(a.status); // 打印授权状态
}

获取授权挑战

对于每个返回的授权,都有多个挑战。可以选择其中一个挑战来证明对标识符的控制权并完成授权请求:

// 获取HTTP挑战数据
for (var a in auth) {
  var data = a.getHttpDcvData();
}

// 获取DNS挑战数据
for (var a in auth) {
  var data = a.getDnsDcvData();
}

自测

建议提前检查挑战是否通过,可以通过适当的方法进行测试。通过maxAttempts参数可以调整尝试次数,默认为15次。

注意: DNS自测使用Google DNS Rest API来获取资源记录。

// 测试HTTP挑战
var self = await client.selfHttpTest(data); // HttpDcvData
if (!self) {
  print('Selftest failed, no file found or content mismatch');
}

// 测试DNS挑战
var self = await client.selfDNSTest(data); // DnsDcvData
if (!self) {
  print('Selftest failed, no DNS record found');
}

触发验证

调用validate()方法通知ACME服务器检查挑战,并每隔4秒轮询一次授权状态,直到状态变为“有效”。默认轮询次数为15次。

// 触发验证
var data; // HttpDcvData 或 DnsDcvData
var authValid = await client.validate(data.challenge);
if (!authValid) {
  print('Authorization failed, exit');
}

完成订单

如果所有授权的状态均为“有效”,则通过发送CSR完成订单。CSR会根据RFC规则自动格式化(Base64Url编码且无头部)。

// 发送CSR完成订单
var finalOrder = await client.finalizeOrder(newOrder, csr);

获取证书

通过getCertificate()方法获取证书列表,传入已完成的订单对象:

// 获取证书
var certs = await client.getCertificate(finalOrder);

// 打印证书
for (var cert in certs) {
  print(cert); // 输出证书内容
}

更多关于Flutter ACME客户端插件ls_acme_client的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter ACME客户端插件ls_acme_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


ls_acme_client 是一个用于 Flutter 的 ACME 客户端插件,它允许你在 Flutter 应用中与 ACME 服务器进行交互,以获取和管理 TLS/SSL 证书。ACME(Automatic Certificate Management Environment)是一个协议,通常与 Let’s Encrypt 等服务一起使用,用于自动化证书的获取和续订。

安装 ls_acme_client

首先,你需要在 pubspec.yaml 文件中添加 ls_acme_client 依赖项:

dependencies:
  flutter:
    sdk: flutter
  ls_acme_client: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖项。

使用 ls_acme_client

以下是一个简单的示例,展示如何使用 ls_acme_client 获取证书:

import 'package:ls_acme_client/ls_acme_client.dart';

void main() async {
  // 创建 ACME 客户端实例
  final acmeClient = AcmeClient(
    directoryUrl: 'https://acme-v02.api.letsencrypt.org/directory', // ACME 服务器目录 URL
  );

  // 创建账户
  final account = await acmeClient.createAccount(
    email: 'your-email@example.com',
    agreeToTerms: true,
  );

  // 创建订单
  final order = await acmeClient.createOrder(
    identifiers: ['example.com', 'www.example.com'],
  );

  // 获取授权
  final authorizations = await acmeClient.getAuthorizations(order);

  // 完成挑战(例如 HTTP-01 挑战)
  for (final auth in authorizations) {
    final challenge = auth.http01Challenge;
    // 在这里,你需要将 challenge.token 和 challenge.keyAuthorization 部署到你的服务器
    // 例如,将 keyAuthorization 放在 `/.well-known/acme-challenge/${challenge.token}` 路径下
    await acmeClient.completeChallenge(challenge);
  }

  // 等待挑战完成
  await acmeClient.waitForAuthorizations(order);

  // 生成 CSR(证书签名请求)
  final csr = generateCsr(
    commonName: 'example.com',
    altNames: ['www.example.com'],
  );

  // 完成订单
  final certificate = await acmeClient.finalizeOrder(order, csr);

  // 下载证书
  final certChain = await acmeClient.downloadCertificate(certificate);

  // 打印证书链
  print(certChain);
}
回到顶部