【问题标题】:Sending HTTP/2 request to Apple Push Notification Service using HttpClient, Client Certificate and WinHttpHandler raises HttpRequestException使用 HttpClient、客户端证书和 WinHttpHandler 向 Apple Push Notification Service 发送 HTTP/2 请求会引发 HttpRequestException
【发布时间】:2020-12-02 11:48:06
【问题描述】:

我正在尝试编写一些代码,以使用 C# .NET 和 HttpClient over HTTP 通过客户端证书身份验证向 iPhone 发送推送通知。

代码编译但总是产生:

带有消息“将内容复制到流时出错”的 HttpRequestException。

InnerException IOException Message "写操作失败,查看内部异常。"

InnerException WinHttpException Message "{"Error 12152 calling WinHttpWriteData, 'The server returned an invalid or unrecognized response'."}"

我正在寻找代码失败的原因?

是否可以通过某种方式调试/排除故障?

这是我的代码

class Program {
    private const string cert = "MIINKwI....<hidden>";
    private const string certpw = "password";
    private const string devicetoken = "921c95b6494828f973512f2327478b0<hidden>";
    private const string bundleid = "se.jensolsson.testapp";

    private static HttpClient client = null;
    static async Task Main(string[] args) {
        try {

            byte[] certificateData = Convert.FromBase64String(cert);
            X509Certificate2 certificate = new X509Certificate2(certificateData, certpw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

            string url = "https://api.push.apple.com:443/3/device/";

            string payload = @"{""aps"":{""alert"":""Test""}}";

            var handler = new WinHttpHandler();
            handler.ClientCertificates.Add(certificate);

            if (client == null)
                client = new HttpClient(handler);

            using (var request = new HttpRequestMessage(HttpMethod.Post, url + devicetoken)) {
                var messageGuid = Guid.NewGuid().ToString();
                request.Version = new Version("2.0");
                request.Content = new StringContent(payload);
                request.Headers.Add("apns-id", messageGuid);
                request.Headers.Add("apns-push-type", "alert");
                request.Headers.Add("apns-priority", "10");
                request.Headers.Add("apns-topic", bundleid);


                using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)) {
                    HttpStatusCode statusCode = response.StatusCode;
                    string reasonPhrase = response.ReasonPhrase;
                    bool success = response.IsSuccessStatusCode;
                }
            }

        }
        catch (ArgumentNullException anu) { }
        catch (InvalidOperationException ioe) { }
        catch (HttpRequestException hre) { }
        catch (TaskCanceledException tce) { }
        catch (Exception e) { }        
    }
}

编辑 @jdweng 实际上尝试过 Wireshark,但由于它是通过 SSL 和加密的,我希望它无法从 Wireshark 读取?我可以看到,连接是从我们的客户端重置的,必须由底层框架完成。

编辑 2: 进一步调查。尝试连接到支持 HTTP2 的开放式 Web 服务器。我以https://nghttp2.org/ 为例。

  1. 将 url 行替换为 string url = "https://nghttp2.org/";
  2. 将请求行替换为using (var request = new HttpRequestMessage(HttpMethod.Get, url)) {

一个非常有趣的发现是,即使我发送了一个 HTTP/2 请求并且它似乎给出了回复,但查看响应对象,版本设置为 1.1

如果我也删除 handler.ClientCertificates.Add(certificate); 行并重试,查看响应对象,版本正确设置为 2.0

因此,一旦将客户端证书添加到处理程序,WinHttpHandler 似乎就会放弃对 HTTP/2 的支持。

编辑 3: 我现在假设这是框架中的一个错误,我在这里发布了一个错误报告:https://github.com/dotnet/runtime/issues/40794

【问题讨论】:

  • 我会使用像 wireshark 或 fiddler 这样的嗅探器并检查响应中的状态。通常为 200 OK,错误为 400/500。我怀疑是 TLS 1.2 问题。 TLS 1.0/1.1 在今年 6 月被许多服务器停用,很多人都遇到了问题。但不确定。您的错误表明您可能得到了 200 OK 并且响应中的数据无法识别。但不确定。这就是为什么嗅探器结果很重要的原因。
  • 嗨,有什么方法可以在 Dot.Net 中使用框架 4.6 上的 WinHttpHandler 实现 apns 推送通知?我收到错误“服务器返回了无效或无法识别的响应”

标签: c# .net apple-push-notifications dotnet-httpclient http2


【解决方案1】:

原来这是不支持的。 主要是因为 Windows 版本中缺少功能。根据 corefx 团队 github 中的评论,这应该适用于 Windows 2004 版,构建 19573+ github discussion。这个版本的问题是它还没有发布,也没有计划什么时候发布。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多