我有以下Javascript代码,当我使用nodejs运行它时工作正常。但是,我想写一些与Dart类似的东西。我已经浏览了Dart文档,找不到任何示例。如果有人能告诉我如何使用Google Dart重写以下内容,我将非常感激。非常感谢提前!
var https = require('https');
var fs = require('fs');
var url = require('url');
var uri = "https://identitysso-api.betfair.com:443/api/certlogin";
var data = 'username=xxxxxxxx&password=xxxxxxxx';
var appKey = 'xxxxxxxxxxxxxx'
var options = url.parse(uri);
options.method = 'POST';
options.headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Application': appKey
};
options.key = fs.readFileSync('client-2048.key');
options.cert = fs.readFileSync('client-2048.crt');
options.agent = new https.Agent(options);
var req = https.request(options, function(res) {
console.log("statusCode:", res.statusCode);
var responseData = "";
res.on('data', function(d) {
responseData += d;
});
res.on('end', function() {
var response = JSON.parse(responseData);
console.log("sessionToken:", response.sessionToken.replace(/\d/g, ''));
});
res.on('error', function(e) {
console.error(e);
});
});
req.end(data);
我已经达到以下目标: -
import 'dart:io';
void main() {
var uri = "https://identitysso-api.betfair.com:443/api/certlogin";
var data = 'username=xxxxxxxx&password=xxxxxxxx';
var appKey = 'xxxxxxxxxxxx';
var method = 'POST';
HttpClient client = new HttpClient();
client.openUrl(method,Uri.parse(uri))
.then((HttpClientRequest request) {
request.headers.set(HttpHeaders.CONTENT_TYPE, 'application/x-www-form-urlencoded');
request.headers.set('X-Application', appKey);
request.write(data);
return request.close();
})
.then((HttpClientResponse response) {
// Process the response.
});
}
但是在文档中找不到任何东西,它告诉你如何将证书添加到HttpClient或HttpRequest?感谢任何帮助提前多多感谢。
答案 0 :(得分:4)
现在可以在Dart中完成在HTTPS请求中发送客户端证书,就像在node.js中一样,从版本1.13.0开始。在发出HTTPS请求之前,可以将PEM格式的客户端证书和密钥添加到默认的SecurityContext对象中。
Dart现在转而使用BoringSSL,这是由Google维护的OpenSSL的一个分支。 BoringSSL使用以PEM格式存储在文件中的X509证书(SSL和TLS使用的证书)。旧版本的Dart使用NSS,它有自己的证书和密钥数据库,使用命令行工具进行维护。 Dart改变了SecureSocket方法的一些参数,并添加了一个SecurityContext类。
SecurityContext.defaultContext是一个对象,它包含众所周知的证书颁发机构的内置可信根,取自Mozilla用于Firefox和NSS的数据库。因此,您的客户端应使用此对象,并将客户端证书和私钥添加到其中,以便它们用于向请求它们的服务器进行身份验证:
Future postWithClientCertificate() async {
var context = SecurityContext.defaultContext;
context.useCertificateChain('client-2048.crt');
context.usePrivateKey('client-2048.key',
password:'keyfile_password');
HttpClient client = new HttpClient(context: context);
// The rest of this code comes from your question.
var uri = "https://identitysso-api.betfair.com:443/api/certlogin";
var data = 'username=xxxxxxxx&password=xxxxxxxx';
var appKey = 'xxxxxxxxxxxx';
var method = 'POST';
var request = await client.openUrl(method,Uri.parse(uri))
request.headers.set(HttpHeaders.CONTENT_TYPE,
'application/x-www-form-urlencoded');
request.headers.set('X-Application', appKey);
request.write(data);
var response = await request.close();
// Process the response.
}
对于SecureServerSocket,函数SecurityContext.useCertificateChain和SecurityContext.usePrivateKey与用于设置服务器证书和密钥的函数相同,但是当上下文用于客户端连接时,它们指定要发送的客户端证书根据要求。
答案 1 :(得分:3)
可以使用带有dart:io
HTTPS请求的客户端证书。然而,由于在Dart中实现SSL / TLS的方式,它有点复杂。
Dart使用Mozilla NSS库进行SSL / TLS。 NSS将其所有密钥和证书存储在数据库中。 SecureSocket.initialize
调用用于选择要使用的NSS数据库。如果未指定数据库,则将使用内置数据库。内置数据库仅包含受信任的根证书。
要使用客户端证书,您需要使用证书和密钥创建NSS数据库。使用NSS certutil
工具操纵数据库,该工具在此处记录:
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_certutil
此示例创建一个包含三个证书的数据库,一个自签名CA,一个localhost服务器证书和一个客户端证书。使用testtest
作为密码。
$ mkdir certdb
$ certutil -N -d sql:certdb
$ certutil -S -s "CN=Example CA" -n my-ca-cert -x -t "TCu,u,u" -5 sslCA -m 1234 -d sql:certdb
回答9和N
$ certutil -S -s "CN=localhost" -n my-server-cert -c "my-ca-cert" -t "u,u,u" -m 730 -d sql:certdb
$ certutil -S -s "CN=sgjesse" -n my-client-cert -c "my-ca-cert" -t "Pu,u,u" -m 731 -d sql:certdb
然后你可以运行这个服务器:
import "dart:async";
import "dart:io";
void serve() {
HttpServer.bindSecure('localhost',
8080,
certificateName: 'my-server-cert',
requestClientCertificate: true).then((server) {
server.listen((HttpRequest request) {
if (request.certificate != null) {
print('Client certificate ${request.certificate.subject}');
} else {
print('No client certificate');
}
request.response.write("Hello");
request.response.close();
});
});
}
void InitializeSSL() {
var testPkcertDatabase = Platform.script.resolve('certdb').toFilePath();
SecureSocket.initialize(database: testPkcertDatabase,
password: 'testtest');
}
void main() {
InitializeSSL();
serve();
}
这个客户:
import "dart:async";
import "dart:io";
void request() {
HttpClient client = new HttpClient();
client.getUrl(Uri.parse("https://localhost:8080/"))
.then((request) => request.close())
.then((response) {
print('Subject: ${response.certificate.subject}');
print('Issuer: ${response.certificate.issuer}');
return response.transform(UTF8.decoder).join('');
})
.then(print);
}
void InitializeSSL() {
var testPkcertDatabase = Platform.script.resolve('certdb').toFilePath();
SecureSocket.initialize(database: testPkcertDatabase,
password: 'testtest');
}
void main() {
InitializeSSL();
request();
}
希望客户提供客户证书。然而,这依赖于NSS选择客户端证书,我不确定这个规则。如果您使用SecureSocket
,则可以明确选择客户端证书,但目前无法使用HTTPS,请参阅https://code.google.com/p/dart/issues/detail?id=8872。
以下是使用SecureSocket
的客户:
import "dart:async";
import "dart:io";
void request() {
SecureSocket.connect('localhost',
8080,
sendClientCertificate: true,
certificateName: 'my-client-cert').then((socket) {
socket.write("GET / HTTP/1.0\r\n\r\n");
socket.listen(print);
});
}
void InitializeSSL() {
var testPkcertDatabase = Platform.script.resolve('certdb').toFilePath();
SecureSocket.initialize(database: testPkcertDatabase,
password: 'testtest');
}
void main() {
InitializeSSL();
request();
}
希望有所帮助。