无法使用C#.NET Core对ING(API.sandbox.ING.com)终结点进行证书授权API调用 任务
我正试图按照本指南进行访问令牌请求。它提供了一个示例来说明如何做到这一点。另一个要求是从Azure函数进行此调用,因此我在VisualStudio2019中创建了一个HTTP触发的Azure函数项目 我对解决问题的尝试 它由4部分组成:无法使用C#.NET Core对ING(API.sandbox.ING.com)终结点进行证书授权API调用 任务,c#,curl,.net-core,httpclient,x509certificate2,C#,Curl,.net Core,Httpclient,X509certificate2,我正试图按照本指南进行访问令牌请求。它提供了一个示例来说明如何做到这一点。另一个要求是从Azure函数进行此调用,因此我在VisualStudio2019中创建了一个HTTP触发的Azure函数项目 我对解决问题的尝试 它由4部分组成: 装货证书 计算机文摘 生成签名 向提供的API端点发出正确的请求 加载证书 在.cer和.key文件中有两个证书作为密钥对提供。一个是验证请求,另一个是创建签名。我已经将公钥和私钥与openssl命令组合到一个.pfx容器中,如下所示: openssl pkcs
.cer
和.key
文件中有两个证书作为密钥对提供。一个是验证请求,另一个是创建签名。我已经将公钥和私钥与openssl
命令组合到一个.pfx
容器中,如下所示:
openssl pkcs12-export-in my.cer-inkey my.key-out mycert.pfx
并使用以下方式加载它们:
公共静态X509Certificate2 GetCertificate(此ExecutionContext ctx,字符串certFileName)
{
返回新的X509Certificate2(Path.GetFullPath(Path.Combine(ctx.FunctionAppDirectory,@$“Certs\{certFileName}”),“mypass”);
}
计算机文摘
我正在使用FormUrlEncodedContent
类作为我的有效负载,因此摘要的计算如下:
公共静态字符串计算SA256HashasBase64String(此字符串stringToHash)
{
使用(var hash=SHA256.Create())
{
Byte[]result=hash.ComputeHash(Encoding.UTF8.GetBytes(stringToHash));
返回Convert.tobase64字符串(结果);
}
}
公共静态异步任务摘要值(此FormUrlEncodedContent内容)
{
var payload=await content.ReadAsStringAsync();
return“SHA-256=“+payload.ComputeSHA256HashAsBase64String()”;
}
生成签名
var currentDate=DateTime.Now.ToUniversalTime().ToString(“r”);
var签名字符串=
@$“(请求目标):{IgnAccountApi.HttpMethodStr}{IgnAccountApi.AccessTokenPath}
日期:{currentDate}
摘要:{摘要}”;
var签名=cert.SignData(signingString);
公共静态字符串SignData(此X509Certificate2证书,字符串stringToSign)
{
使用(var hash=SHA256.Create())
{
var dataToSign=Encoding.UTF8.GetBytes(stringToSign);
字节[]hashToSign=hash.ComputeHash(dataToSign);
var signedData=cert.GetRSAPrivateKey().SignData(hashToSign,HashAlgorithmName.SHA256,rsasignatureAdding.Pkcs1);
返回Convert.tobase64字符串(signedData);
}
}
提出请求
我试图重现的curl
请求():
curl-v-i-X POST“${httpHost}${reqPath}”\
-H'Accept:application/json'\
-H'内容类型:应用程序/x-www-form-urlencoded'\
-H“摘要:${Digest}”\
-H“日期:${reqDate}”\
-H“授权:签名keyId=\”$keyId\”,算法=\“rsa-sha256\”,头=\“(请求目标)日期摘要\”,签名=\“$Signature\”\
-d“${payload}”\
--证书“${certPath}示例\u客户端\u tls.cer”\
--密钥“${certPath}示例\u客户端\u tls.key”
我正在使用HttpClientHandler
将我使用openssl
创建的tls.pfx
添加到HttpClient
中,并发出如下授权请求:
使用(var cert=ctx.GetCertificate(“tls.pfx”))
{
// https://stackoverflow.com/questions/40014047/add-client-certificate-to-net-core-httpclient
var_clientHandler=新的HttpClientHandler();
_clientHandler.ClientCertificates.Add(cert);
_clientHandler.ClientCertificateOptions=ClientCertificateOptions.Manual;
_clientHandler.SslProtocols=SslProtocols.Tls12;
var dataToSend=新字典
{
{“授权类型”、“客户端凭据”},
};
使用(var content=newformurlencodedcontent(dataToSend))
使用(var\u client=newhttpclient(\u clientHandler))
{
var request=newhttprequestmessage(HttpMethod.Post,$“{HttpHost}{AccessTokenPath}”);
request.Content=内容;
request.AddHeaders(ctx.GetCertificate(“sign.pfx”),wait content.DigestValue();
使用(HttpResponseMessage response=wait_client.SendAsync(请求))
{
//TODO:处理响应
}
}
}
为了不遗漏任何内容,这里有AddHeaders
扩展方法:
publicstaticvoidaddheaders(此HttpRequestMessage请求,X509Certificate2证书,字符串摘要)
{
var currentDate=DateTime.Now.ToUniversalTime().ToString(“r”);
var签名字符串=
@$“(请求目标):{IgnAccountApi.HttpMethodStr}{IgnAccountApi.AccessTokenPath}
日期:{currentDate}
摘要:{摘要}”;
var签名=cert.SignData(signingString);
添加(“接受”、“应用程序/json”);
添加(“摘要”,摘要);
请求。标题。添加(“日期”,currentDate);
Add(“authorization”、$“Signature keyId=\”{IgnacountAPI.ClienId}\”,算法=\“rsa-sha256\”,头=\“(请求目标)日期摘要\”,签名=“{Signature}\”;
}
上述代码生成以下请求:
POST https://api.sandbox.ing.com/oauth2/token HTTP/1.1
Host: api.sandbox.ing.com
Accept: application/json
Digest: SHA-256=w0mymuL8aCrbJmmabs1pytZhon8lQucTuJMUtuKr+uw=
Date: Tue, 21 Apr 2020 09:02:56 GMT
Authorization: Signature keyId="e77d776b-90af-4684-bebc-521e5b2614dd",algorithm="rsa-sha256",headers="(request-target) date digest",signature="BaQgDXTsGBcZfZa+9oeaQhkv7bQwbMw92h4Dwp/EexJnjScScqVMYFwRSskkN1fYfu/1lDE+/K27qEJD9cq8i68C6u29I9wsUWlRtAiHu10d/hzTcZkfWLpoSKSo4mg016I//K/4scdnwf0fcsNgDOXYaoe9/KscltreXn6UQuYuwP98uZDTP3j/V7k34R5VIMPaUm1MSvE3H5opGNbLqpBjK8IenKUHjF0B9aqCzGB30eA7Y+fL025wRko6mGY2f+u4w3mi1RJzTb72Cw3SPejaa5s65sYIAus14g975RPBI4B7A2o/vsZ39Np1yJNvCW1tbZaTGAF4IJUfXQashw=="
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
grant_type=client_credentials
我得到的答复相当令人失望:
HTTP/1.1 400
Date: Sat, 18 Apr 2020 06:17:20 GMT
Content-Type: application/json
Content-Length: 98
Connection: keep-alive
X-Frame-Options: deny
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31622400; includeSubDomains
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Content-Security-Policy: default-src 'self'; prefetch-src 'none'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; upgrade-insecure-requests; block-all-mixed-content; connect-src 'self'; style-src 'self' 'unsafe-inline' data:; img-src https: data:; script-src 'self' data: 'unsafe-inline' 'unsafe-eval'
{
"message" : "InputValidation failed: Field 'X-ENV-SSL_CLIENT_CERTIFICATE' was not provided."
}
为了比较从curl发出的请求,下面是使用提供的bash脚本生成的请求(不幸的是fiddler没有看到这个,所以它只是从控制台窗口复制/粘贴):
问题
我做错了什么?是否可以使用HttpClient
类使用证书对请求进行身份验证?请帮忙
更新1:添加了由我的代码生成的HTTP请求和由()提供的上述bash脚本生成的HTTP请求。我认为我们正在处理相同的问题 但在您的代码中,看起来他们要求的是SSL证书,而不是TLS(或两者兼而有之)。您可能需要:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls | SecurityProtocolType.Tls11;
在ING开发环境中,有两个独立的证书-SSL和TLS您可以发布实际发送的请求吗?您是否检查了入门文档中记录的内容之间的差异
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls | SecurityProtocolType.Tls11;