如何使用证书从 flutter app 发送 AWS iot http 请求?
How to send AWS iot http request from flutter app using certificates?
我正在尝试使用 flutter 应用程序向 AWS IoT 发布消息。
根据我尝试复制的 AWS 文档
curl --tlsv1.2 \
--cacert Amazon-root-CA-1.pem \
--cert device.pem.crt \
--key private.pem.key \
--request POST \
--data "{ \"message\": \"Hello, world\" }" \
"https://IoT_data_endpoint:8443/topics/topic?qos=1"
这是我试过的
final List<int> trustedCertificateBytes =
(await rootBundle.load('assets/certificates/AmazonRootCA1.pem'))
.buffer
.asInt8List();
final List<int> certificateChainBytes = (await rootBundle.load(
'assets/certificates/device.pem.crt'))
.buffer
.asInt8List();
final List<int> privateKeyBytes = (await rootBundle.load(
'assets/certificates/private.pem.key'))
.buffer
.asInt8List();
final data = jsonEncode(
<String, dynamic>{"message": "hello world"},
);
final context = SecurityContext.defaultContext;
context.setTrustedCertificatesBytes(trustedCertificateBytes);
context.useCertificateChainBytes(certificateChainBytes);
context.usePrivateKeyBytes(privateKeyBytes);
final client = HttpClient(context: context);
final request = await client.openUrl(
'POST', Uri.parse("https://$myEndpoint/topics/some_topic?qos=1"));
request.write(data);
try {
final response = await request.close();
print("success");
print(response);
response.transform(utf8.decoder).listen((contents) {
print(contents);
});
} catch (e) {
print(e);
}
第一次 api 调用时,http 调用成功,但响应为 {"message":"Missing authentication","traceId":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"}
在每次后续调用时,flutter 都会抛出此错误:
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: TlsException: Failure trusting builtin roots (OS Error: CERT_ALREADY_IN_HASH_TABLE(x509_lu.c:356), errno = 0)
关于如何让它工作的任何想法?
-- 编辑部分: 第一个调用问题已解决,添加 context.setAlpnProtocols(["x-amzn-http-ca"], false);
非常有效。后续调用问题依然存在
OP在这里。
为上下文设置 alpn 协议解决了身份验证令牌问题
...
context.setAlpnProtocols(["x-amzn-http-ca"], false);
...
然后我设置了一个全局标志来判断证书是否已经设置。如果已设置,则无需重新设置。
全球范围
bool setCert = false;
函数范围
if (!setCert){
// Set certificates & alpn protocol here
setCert = true;
}
它解决了第二个问题。
我认为这是因为您要在后续调用中向 SecurityContext.defaultContext
添加并重新添加证书。
您可以尝试创建一个新的 SecurityContext
每次都这样做。
var sec = SecurityContext();
sec.set....
我正在尝试使用 flutter 应用程序向 AWS IoT 发布消息。
根据我尝试复制的 AWS 文档
curl --tlsv1.2 \
--cacert Amazon-root-CA-1.pem \
--cert device.pem.crt \
--key private.pem.key \
--request POST \
--data "{ \"message\": \"Hello, world\" }" \
"https://IoT_data_endpoint:8443/topics/topic?qos=1"
这是我试过的
final List<int> trustedCertificateBytes =
(await rootBundle.load('assets/certificates/AmazonRootCA1.pem'))
.buffer
.asInt8List();
final List<int> certificateChainBytes = (await rootBundle.load(
'assets/certificates/device.pem.crt'))
.buffer
.asInt8List();
final List<int> privateKeyBytes = (await rootBundle.load(
'assets/certificates/private.pem.key'))
.buffer
.asInt8List();
final data = jsonEncode(
<String, dynamic>{"message": "hello world"},
);
final context = SecurityContext.defaultContext;
context.setTrustedCertificatesBytes(trustedCertificateBytes);
context.useCertificateChainBytes(certificateChainBytes);
context.usePrivateKeyBytes(privateKeyBytes);
final client = HttpClient(context: context);
final request = await client.openUrl(
'POST', Uri.parse("https://$myEndpoint/topics/some_topic?qos=1"));
request.write(data);
try {
final response = await request.close();
print("success");
print(response);
response.transform(utf8.decoder).listen((contents) {
print(contents);
});
} catch (e) {
print(e);
}
第一次 api 调用时,http 调用成功,但响应为 {"message":"Missing authentication","traceId":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"}
在每次后续调用时,flutter 都会抛出此错误:
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: TlsException: Failure trusting builtin roots (OS Error: CERT_ALREADY_IN_HASH_TABLE(x509_lu.c:356), errno = 0)
关于如何让它工作的任何想法?
-- 编辑部分: 第一个调用问题已解决,添加 context.setAlpnProtocols(["x-amzn-http-ca"], false);
非常有效。后续调用问题依然存在
OP在这里。
为上下文设置 alpn 协议解决了身份验证令牌问题
...
context.setAlpnProtocols(["x-amzn-http-ca"], false);
...
然后我设置了一个全局标志来判断证书是否已经设置。如果已设置,则无需重新设置。
全球范围
bool setCert = false;
函数范围
if (!setCert){
// Set certificates & alpn protocol here
setCert = true;
}
它解决了第二个问题。
我认为这是因为您要在后续调用中向 SecurityContext.defaultContext
添加并重新添加证书。
您可以尝试创建一个新的 SecurityContext
每次都这样做。
var sec = SecurityContext();
sec.set....