无法使用C#.NET Core对ING(API.sandbox.ING.com)终结点进行证书授权API调用 任务

无法使用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

我正试图按照本指南进行访问令牌请求。它提供了一个示例来说明如何做到这一点。另一个要求是从Azure函数进行此调用,因此我在VisualStudio2019中创建了一个HTTP触发的Azure函数项目

我对解决问题的尝试 它由4部分组成:

  • 装货证书
  • 计算机文摘
  • 生成签名
  • 向提供的API端点发出正确的请求
  • 加载证书 在
    .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;