我正在尝试使用Linux下的mono和F#对https网页执行简单的Web请求。
我昨天设法通过禁用ServerCertificateValidationCallback
完成的证书验证来获得解决方案,但现在它突然停止工作了。
我的脚本的相关部分看起来像这样
#r "../../packages/FSharp.Data/lib/net40/FSharp.Data.dll"
#r "System.Xml.Linq.dll"
open FSharp.Data
open System
open System.IO
open System.Net
open System.Net.Security
open System.Threading
open System.Security.Cryptography.X509Certificates
// disabling certificate validation
ServicePointManager.ServerCertificateValidationCallback <-
new RemoteCertificateValidationCallback(fun _ _ _ _ -> true)
type Either<'a,'b> = Left of 'a
| Right of 'b
let web_reader (url: string) =
try
Thread.Sleep 500
let wr = WebRequest.CreateHttp url
wr.UserAgent <- "test.bot" //I've also tried "safari" without luck
let stream = wr.GetResponse().GetResponseStream()
Right( (new StreamReader(stream)).ReadToEnd() )
with exp -> Left (sprintf "ERROR IN 'web_reader' FOR URL %s\n\n%A" url exp)
web_reader "https://www.jobfinder.dk/"
并调用应用于https网址的web_reader
函数会导致以下异常
System.Net.WebException: Error: SendFailure (Error writing headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The authentication or decryption has failed.
at Mono.Security.Protocol.Tls.RecordProtocol.EndReceiveRecord (IAsyncResult asyncResult) <0x41d866e0 + 0x0010b> in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslClientStream.SafeEndReceiveRecord (IAsyncResult ar, Boolean ignoreEmpty) <0x41d86620 + 0x0002b> in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslClientStream.NegotiateAsyncWorker (IAsyncResult result) <0x41d838e0 + 0x00227> in <filename unknown>:0
--- End of inner exception stack trace ---
at System.Net.WebConnection.EndWrite (System.Net.HttpWebRequest request, Boolean throwOnError, IAsyncResult result) <0x41d87f00 + 0x00207> in <filename unknown>:0
at System.Net.WebConnectionStream+<SetHeadersAsync>c__AnonStorey1.<>m__0 (IAsyncResult r) <0x41d87800 + 0x0013b> in <filename unknown>:0
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) <0x41d74070 + 0x0019f> in <filename unknown>:0
at System.Net.HttpWebRequest.GetResponse () <0x41d6ee90 + 0x00053> in <filename unknown>:0
at FSI_0001.web_reader (System.String url) <0x41d8a4a0 + 0x00073> in <filename unknown>:0
我真的没有弄错。我错过了什么?
我正在使用:
我一直非常小心,不要对该网址执行太多请求,我甚至在Thread.Sleep
添加了一些延迟。我仍然可以ping服务器并访问给定的网站,所以我怀疑他们阻止了我的IP或类似的东西。第一次尝试时会抛出异常。
修改
我刚用.Net测试了Visual Studio中的代码,似乎请求永远停滞不前。所以我进行了调试和调查,最终找到了解决方案The request was aborted: Could not create SSL/TLS secure channel
在我的脚本中添加以下内容:
ServicePointManager.Expect100Continue <- true;
ServicePointManager.SecurityProtocol <- SecurityProtocolType.Tls12
然后它适用于.Net。
我还将我的单声道版本从4.2.1更新到4.4.1,它似乎也支持Tls12,但是我仍然无法使用单声道。