问题
This is similar to this question: Force TLS > 1.0 on AppEngine local development server in Java except that the answer doesn't work because it assumes a static SDK location(?).
I have a Google App Engine application that uses a third party payment library (braintree) that communicates over HTTPS using TLSv1.2. However, whenever the braintree library makes calls to the braintree sandbox environment the resulting urlfetch
always gives the following error:
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)
Whilst this error only happens on the App Engine development server (and not when deployed into App Engine land), it still means that I can't test the stuff I need to in development.
According to this: https://groups.google.com/forum/#!topic/google-appengine-stackoverflow/tdr4T1CJRn8 the problem is that App Engine isn't using TLSv1.2.
My application is an App Engine app (Standard Environment) using the SDK version 1.9.26.
The appengine
section of my gradle configuration looks like so:
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
}
}
I have tried updating the dev_appserver.sh in my local appengine-sdk directory to read:
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 "$@"
and setting downloadSdk = false
and setting the appengine.sdk.root
so that the gradle appengineRun
task actually uses it.
I cannot use Java 8.
I have also tried putting this in my code:
System.setProperty("https.protocols", "TLSv1.2");
None of this works. Either I'm barking up the wrong tree, and trying all the wrong things, or I'm doing something wrong.
How can I get this to work?
Update:
It looks like the problem is actually that the sslSocketFactory is never created, because urlfetch will never return an HttpsURLConnection
(App Engine URLfetch to validate self-signed certificate)
Still searching for a resolution.
回答1:
To fix this I had to run the project locally under the Java 8 SDK. Even though Java 8 isn't supported on App Engine yet, at least I can make Braintree sandbox payments in development and actually test my workflow.
I can then rely on the build server to check it still builds under Java 7.
To do this in IntelliJ:
⌘
+;
to bring up Project Settings, then change the Project SDK to Java 1.8:
⌘
+,
to bring up Preferences, then change the Gradle JVM option to Use Project JDK
:
Then run gradle clean build
. Then run the appengineRun
gradle task to start up the dev system and all should be fine.
As mentioned in the second answer here: Force TLS > 1.0 on AppEngine local development server in Java Java 8 uses TLSv1.8 by default.
Even though it feels totally wrong developing and testing your app on a JRE other than the one it will actually be run on, needs must. :(
来源:https://stackoverflow.com/questions/43919057/force-tls-1-2-on-appengine-dev-server-sdk