在 Appengine 开发服务器 SDK 上强制使用 TLS 1.2

Force TLS 1.2 on appengine dev server SDK

这与这个问题类似:Force TLS > 1.0 on AppEngine local development server in Java 除了答案不起作用,因为它假定静态 SDK 位置(?)。

我有一个 Google App Engine 应用程序,它使用第三方支付库 (braintree),使用 TLSv1.2 通过 HTTPS 进行通信。但是,每当 braintree 库调用 braintree 沙箱环境时,结果 urlfetch 总是给出以下错误:

Caused by: javax.net.ssl.SSLHandshakeException: Could not verify SSL certificate for URL: https://api.sandbox.braintreegateway.com:443/merchants/**********/client_token
    at com.google.appengine.api.urlfetch.URLFetchServiceImpl.convertApplicationException(URLFetchServiceImpl.java:174)
    at com.google.appengine.api.urlfetch.URLFetchServiceImpl.fetch(URLFetchServiceImpl.java:43)
    at com.google.apphosting.utils.security.urlfetch.URLFetchServiceStreamHandler$Connection.fetchResponse(URLFetchServiceStreamHandler.java:543)
    at com.google.apphosting.utils.security.urlfetch.URLFetchServiceStreamHandler$Connection.getInputStream(URLFetchServiceStreamHandler.java:422)
    at com.google.apphosting.utils.security.urlfetch.URLFetchServiceStreamHandler$Connection.getResponseCode(URLFetchServiceStreamHandler.java:275)
    at com.braintreegateway.util.Http.httpRequest(Http.java:120)

虽然这个错误只发生在 App Engine 开发服务器上(而不是在部署到 App Engine 领域时),但这仍然意味着我无法测试我在开发中需要的东西。

据此:https://groups.google.com/forum/#!topic/google-appengine-Whosebug/tdr4T1CJRn8问题是 App Engine 没有使用 TLSv1.2。

我的应用程序是使用 1.9.26 版 SDK 的 App Engine 应用程序(标准环境)。

我的 gradle 配置的 appengine 部分如下所示:

appengine {
    httpAddress = "0.0.0.0"
    httpPort = 8888
    downloadSdk = false

    appcfg {
        update {
            useJava7 = true
        }

        jvmFlags = ['-Ddatastore.backing_store=../../src/main/webapp/WEB-INF/appengine-generated/local_db.bin',
                    // Desperation:
                    '-Ddeployment.security.TLSv1.0=false',
                    '-Ddeployment.security.TLSv1.1=false',
                    '-Ddeployment.security.TLSv1.2=true',
                    '-Dhttps.protocols=TLSv1.2',
                    '-Dappengine.fullscan.seconds=5',
                    '-Xdebug',
                    '-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8889',
                    '-XX:MaxPermSize=512m']
        oauth2 = true
        extraOptions = appCfgOpts
    }

    enhancer {
        api = "jdo"
        version = "v1"
        enhanceOnBuild = true
    }

}

我已尝试将本地 appengine-sdk 目录中的 dev_appserver.sh 更新为:

exec "${RUN_JAVA}" "${SCRIPT_NAME}" \
    -Dhttps.protocols=TLSv1.2 -Ddeployment.security.TLSv1.0=false -Ddeployment.security.TLSv1.1=false -Ddeployment.security.TLSv1.2=true -ea -cp "${JAR_FILE}" \
    com.google.appengine.tools.KickStart \
    com.google.appengine.tools.development.DevAppServerMain "$@"

并设置 downloadSdk = false 并设置 appengine.sdk.root 以便 gradle appengineRun 任务实际使用它。

我无法使用 Java 8. 我也试过把这个放在我的代码中: System.setProperty("https.protocols", "TLSv1.2");

None 的作品。要么我找错了树,尝试了所有错误的事情,要么我做错了什么。

我怎样才能让它工作?

更新:

看起来问题实际上是从未创建 sslSocketFactory,因为 urlfetch 永远不会 return HttpsURLConnection (App Engine URLfetch to validate self-signed certificate)

仍在寻找解决方案。

为了解决这个问题,我不得不在 Java 8 SDK 下 运行 本地项目。尽管 App Engine 尚不支持 Java 8,但至少我可以在开发中进行 Braintree 沙箱支付并实际测试我的工作流程。

然后我可以依靠构建服务器来检查它是否仍然在 Java 7 下构建。

要在 IntelliJ 中执行此操作:

+;调出Project Settings,然后将Project SDK改为Java 1.8:

+, 调出首选项,然后将 Gradle JVM 选项更改为 Use Project JDK

然后运行gradle clean build。然后 运行 appengineRun gradle 启动开发系统的任务,一切都应该没问题。

如此处第二个答案所述:Force TLS > 1.0 on AppEngine local development server in Java Java 8 默认使用 TLSv1.8。

尽管在实际 运行 之外的 JRE 上开发和测试您的应用程序感觉完全错误,但必须如此。 :(