RCurl

时间:2016-06-30 18:01:28

标签: r rcurl

  

ETA:根据https://github.com/hiratake55/RForcecom/issues/42,看起来rforcecom软件包的作者已经更新rforcecom以使用httr而不是RCurl(截至今天,明天将于2016年7月1日上传到CRAN),所以我的具体问题将在那时得到解决。但是,一般情况(在RCurl中实施TLS 1.1 / 1.2)可能仍然值得追求其他包。或者每个人都可以切换到更新的curl包而不是RCurl。

背景:我一直在使用rforcecom软件包与Salesforce沟通几个月。 Salesforce最近禁用了对TLS v1.0的支持,并且要求其沙箱中使用TLS v1.1或更高版本;此更新将于2017年3月针对生产环境进行。

rforcecom使用RCurl与salesforce.com服务器进行通信。通常使用curlPerform方法,它是这样实现的(这个例子来自rforcecom.login.R):

h <- basicHeaderGatherer()
t <- basicTextGatherer()
URL <- paste(loginURL, rforcecom.api.getSoapEndpoint(apiVersion), sep="")
httpHeader <- c("SOAPAction"="login","Content-Type"="text/xml")
curlPerform(url=URL, httpheader=httpHeader, postfields=soapBody, headerfunction = h$update, writefunction = t$update, ssl.verifypeer=F)

正如我所提到的,这对我来说已经有一段时间了。现在,Salesforce已禁用Sandboxes上的TLS v1.0,但它失败并出现以下错误:

UNSUPPORTED_CLIENT: TLS 1.0 has been disabled in this organization. Please use TLS 1.1 or higher when connecting to Salesforce using https.

我已经修改并获得了源代码(没有在软件包的本地副本中实现,因为我没有足够的经验来做到这一点)更改了我的RForcecom登录模块的本地副本,我发现了通过实验,我可以通过向调用它的curlPerform选项添加sslversion=SSLVERSION_TLSv1sslversion=SSLVERSION_SSLv3等来成功指定SSLVERSION的任何现有枚举值。但是,所有这些都给我带来了与上面相同的错误。当我尝试使用libcurl中实现但未在RCurl(SSLVERSION_TLSv1.1SSLVERSION_TLSv1.2)中实现的选项之一时,出现以下错误:

Error in merge(list(...), .opts) : object 'SSLVERSION_TLSv1.1' not found

或:

Error in merge(list(...), .opts) : object 'SSLVERSION_TLSv1.2' not found

我已经使用curlVersion()验证我的libcurl版本是7.40.0,根据https://curl.haxx.se/libcurl/c/CURLOPT_SSLVERSION.html确实支持这些选项。但是,我无法让RCurl识别它们。

此时我正在寻找的是一种让RCurl使用TLS v1.1或TLS v1.2的方法,我非常感谢能够获得的任何帮助。对于我的问题的任何问题/问题我道歉,因为这是我第一次自己问一个问题,我以前总是能够通过阅读其他人的问题和答案而糊里糊涂。

1 个答案:

答案 0 :(得分:1)

RCurl是libcurl的接口,它支持的内容取决于后者。您的libcurl可能是使用较旧版本的OpenSSL构建的,该版本不支持TLS v1.1或v.1.2。您可以像这样从R确定您的SSL版本:

RCurl::curlVersion()$ssl_version

我认为默认情况下(例如ssl选项CURL_SSLVERSION_DEFAULT),在SSL握手期间,服务器和客户端会同意他们都支持的最新版本。要使其工作,您必须将OpenSSL更新为更新版本,使用它重新编译libcurl并重建RCurl以便它注册更新。

也就是说,您可以通过自己传递所需选项的整数值来强制执行未在RCurl中定义的特定ssl版本。您要查找的数字可以从C enum中定义的the curl header file on GitHub中推断出来:

enum {
  CURL_SSLVERSION_DEFAULT, // 0
  CURL_SSLVERSION_TLSv1, /* TLS 1.x */ // 1
  CURL_SSLVERSION_SSLv2, // 2
  CURL_SSLVERSION_SSLv3, // 3
  CURL_SSLVERSION_TLSv1_0, // 4
  CURL_SSLVERSION_TLSv1_1, // 5
  CURL_SSLVERSION_TLSv1_2, // 6
  CURL_SSLVERSION_TLSv1_3, // 7

  CURL_SSLVERSION_LAST /* never use, keep last */ // 8
};

例如:

# the data of you post request
nameValueList = list(data1 = "data1", data2 = "data2")

CURL_SSLVERSION_TLSv1_1 <- 5L
CURL_SSLVERSION_TLSv1_2 <- 6L

# TLS 1.1
opts <- RCurl::curlOptions(verbose = TRUE,
                           sslversion = CURL_SSLVERSION_TLSv1_1, ...)

# TLS 1.2
opts <- RCurl::curlOptions(verbose = TRUE,
                           sslversion = CURL_SSLVERSION_TLSv1_2, ...)

# finally, POST the data
RCurl::postForm(URL, .params = nameValueList, .opts = opts)

一般来说,这可能不是一个好习惯,因为cURL的作者可以决定改变这些选项的价值(尽管我认为机会很低)。