我注意到GraphServiceClient在我的.net框架4.6.1 MVC Web应用程序中连接到Microsoft的Graph API的奇怪行为。我使用System.Net.WebClient从中获取或刷新访问令牌https://login.microsoftonline.com/common/oauth2/v2.0而且效果很好。
但是,使用GraphServiceClient使用Microsoft的Graph API在某些情况下失败,返回以下异常:
[AuthenticationException:远程证书根据验证程序。]
System.Net.TlsStream.EndWrite(IAsyncResult-asyncResult)+300
System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult-ar)+180[WebException:基础连接已关闭:无法为SSL/TLS安全通道建立信任关系。]
。。。(为了简洁起见,我删掉了其余部分)
我尝试/检查的内容:
- 来自graph.Microsoft.com/的证书(Microsoft的)在我的计算机上是有效和受信任的,并且链中似乎不包含其他(代理)证书
- 对ServicePointManager.ServerCertificateValidationCallback使用返回true的回调始终有效(不再抛出异常),但我不希望在代码中使用此破解
- 当调试来自上述破解的ServerCertificateValidationCallback时,sslPolicyErrors参数似乎总是设置为"sslPolicyErrors.none",那么证书验证什么时候失败呢
-
-使用System.Net.WebClient来使用图API而不是GraphServiceClient,始终有效。GraphServiceClient在证书检查方面比System.Net.WebClient做得更多的是什么(编辑:我的错:Web客户端的ServicePointManager.ServerCertificateValidationCallback返回true) - 使用Postman使用相同的访问令牌来消费图API就可以了
-
使用System.Net.WebClient,然后使用GraphServiceClient获取相同的数据(请参阅下面的代码),这样我就可以让GraphService客户端工作,只是它前面必须有使用System.Net.WebClient连接到API的其他代码(这实际上是最奇怪的部分)(编辑:我的错:这很正常,因为Web客户端有ServicePointManager.ServerCertificateValidationCallback返回true) - 在我们的暂存环境中,GraphServiceClient可以正常工作(没有黑客或之前的WebClient代码),所以我想这是我的开发PC上的一些东西和GraphServiceClient的使用的结合
- 我的电脑上确实有活动的Cisco AMP(但我无法关闭它)。我们的网络中没有代理服务器
代码:
private static GraphServiceClient GetGraphClient(string accessToken) {
return new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) => {
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
return Task.FromResult(0);
}));
}
async public static Task<List<Appointment>> GetAppointments(string accessToken, int eventsAmountToGet) {
List<QueryOption> queryOptions = new List<QueryOption>(){
new QueryOption("startDateTime", DateTime.UtcNow.ToString("o")),
new QueryOption("endDateTime", DateTime.UtcNow.AddDays(30).ToString("o"))
};
GraphServiceClient graphClient = GetGraphClient(accessToken);
//the following line will fail (remote certificate ...)
IUserCalendarViewCollectionPage result = await graphClient.Me.CalendarView.Request(queryOptions).GetAsync();
return result.Select(x => new Appointment {
Subject = x.Subject.ToString(),
Start = x.Start.ToDateTime(),
End = x.End.ToDateTime(),
Organiser = x.Organizer.EmailAddress.Name
}).Take(eventsAmountToGet).ToList();
}
编辑:当使用"ServicePointManager.ServerCertificateValidationCallback return true"破解时,我在Fiddler中看到了这些数据。让我担心的是请求中的"时间"字符串,它似乎已经过去了。这个字符串是从哪里生成的?
原始请求:
CONNECT graph.microsoft.com/443 HTTP/1.1主机:graph.microsoft.com
找到了SSLv3兼容的ClientHello握手。小提琴手提取以下参数。
版本:3.3(TLS/1.2)随机:5E 67 B7 58 60 39 A6 18 3B 07 3C F0 8817 E4 85 A7 3C 58 76 85 DE F4 0F EF 4C 76 ED DB 10 52 DE"时间":2017年3月2日1:29:18会话ID:43 4C 00 00 8C 73 51 69 9E 8B FB 24 8B E26B C2 B5 AA 0B E1 45 20 80 F4 98 BE A2 03 DF 1E D8 B3接长件:server_name graph.microsoft.com supported_groups x25519[0x1d],secp256r1[0x17],secp384r1[0x18]ec_point_formats未压缩[0x0]签名_,rsa_ccs1_sha1、ecdsa\usecp256r1_sha256、ecdson\usecp384r1_sha384,ecdsa_sha1、dsa\usha1、rsa_ccs1_sha512、ecdsa\usecp521r1_sha512会话票证为空extended_master_secret为空representation_info 00密码:[C02C]TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384[C02B]TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256[C030]TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384[C02F]TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256[009F]TLS_DHE_RSA_WITH_AES_256_GCM_SHA384[009E]TLS_DHE_RSA_WITH_AES_128_GCM_SHA256[C024]TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384[C023]TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256[C028]TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384[C027]TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256[C00A]TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA[C009]TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA[C014]TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA[C013]TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA[0009d]TLS_RSA_WITH_AES_256_GCM_SHA384[009C]TLS_RSA_WITH_AES_128_GCM_SHA256[003D]TLS_RSA_WITH_AES_256_CBC_SHA256[003C]TLS_RSA_WITH_AES_128_CBC_SHA256[0035]TLS_RSA_WITH_AES_256_CBC_SHA[002F]TLS_RSA_WITH_AES_128_CBC_SHA[000A]SSL_RSA_WITH_3DES_EDE_SHA
压缩:[00]NO_Compression
原始响应:
HTTP/1.1 200连接建立的FiddlerGateway:直接启动时间:16:50:48.111连接:关闭
加密的HTTPS流量流经此CONNECT隧道。HTTPSFiddler中启用了解密,因此解密会话在中运行此隧道将显示在"Web会话"列表中。
安全协议:Tls12密码:Aes128 128位哈希算法:Sha256?位密钥交换:ECDHE_RSA(0xae06)255位
===服务器证书======[主题]CN=graph.microsoft.com
[颁发者]CN=Microsoft IT TLS CA 2,OU=Microsoft IT,O=MicrosoftCorporation,L=雷德蒙德,S=华盛顿,C=美国
【序列号】20000549F729A8A47312D9F3220000000549F7
【之前】2019年1月27日20:09:45
【不在此之后】2021年1月27日20:09:45
[指纹]2D4A597DE7EA5A28474EEAB141E8A085907A900A
[SubjectAltNames]graph.microsoft.com
找到它了。罪魁祸首是dropbox API客户端,我也在同一个web应用程序中使用它。特别是这一行代码:
DropboxCertHelper.InitializeCertPinning();
这行代码还实现ServicePointManager.ServerCertificateValidationCallback,并可能使用HttpClient或WebClient中断其他代码。
更多信息https://github.com/dropbox/dropbox-sdk-dotnet/issues/74