Grails 通过SSL使用HttpBuilder上载文件

Grails 通过SSL使用HttpBuilder上载文件,grails,ssl,groovy,https,httpbuilder,Grails,Ssl,Groovy,Https,Httpbuilder,我正在尝试使用HttpBuilder将文件上载到通过SSL运行的web服务。我是从一个Gradle构建文件来做这件事的,但我认为这并不重要。web服务是Grails应用程序的一部分,但同样,这并不重要 我的grails应用程序在本地通过SSL运行,当您告诉它通过https运行时,它会使用grails生成的证书。我在本地工作的代码如下: def http = new groovyx.net.http.HTTPBuilder( 'https://localhost:8443/' ) //=== S

我正在尝试使用HttpBuilder将文件上载到通过SSL运行的web服务。我是从一个Gradle构建文件来做这件事的,但我认为这并不重要。web服务是Grails应用程序的一部分,但同样,这并不重要

我的grails应用程序在本地通过SSL运行,当您告诉它通过https运行时,它会使用grails生成的证书。我在本地工作的代码如下:

def http = new groovyx.net.http.HTTPBuilder( 'https://localhost:8443/' )

//=== SSL UNSECURE CERTIFICATE ===
def sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, [ new X509TrustManager() {
  public X509Certificate[] getAcceptedIssuers() {null }
  public void checkClientTrusted(X509Certificate[] certs, String authType) { }
  public void checkServerTrusted(X509Certificate[] certs, String authType) { }
} ] as TrustManager[], new SecureRandom())
def sf = new SSLSocketFactory(sslContext)
def httpsScheme = new Scheme("https", sf, 8443)
http.client.connectionManager.schemeRegistry.register( httpsScheme )

http.request( groovyx.net.http.Method.POST, groovyx.net.http.ContentType.JSON ) { req ->
    uri.path = '/a/admin/runtime/upload'
    uri.query = [ username: "username", password: "password", version: version]
    requestContentType = 'multipart/form-data'
    org.apache.http.entity.mime.MultipartEntity entity = new org.apache.http.entity.mime.MultipartEntity()
    def file = new File("file.zip")
    entity.addPart("runtimeFile", new org.apache.http.entity.mime.content.ByteArrayBody(file.getBytes(), 'file.zip'))
    req.entity = entity
}
def http = new groovyx.net.http.HTTPBuilder( 'https://www.realserver.com/' )

http.request( groovyx.net.http.Method.POST, groovyx.net.http.ContentType.JSON ) { req ->
    uri.path = '/a/admin/runtime/upload'
    uri.query = [ username: "username", password: "password" ]
    requestContentType = 'multipart/form-data'
    org.apache.http.entity.mime.MultipartEntity entity = new org.apache.http.entity.mime.MultipartEntity()
    def file = new File("file.zip")
    entity.addPart("runtimeFile", new org.apache.http.entity.mime.content.ByteArrayBody(file.getBytes(), 'file.zip'))
    req.entity = entity
}
顶部的垃圾是我发现的一些代码,它允许HttpBuilder使用自签名证书。这实际上在本地起作用。HttpBuilder文档说,大多数情况下,SSL应该可以正常工作。因此,我使用合法购买的认证通过SSL执行此操作的代码如下:

def http = new groovyx.net.http.HTTPBuilder( 'https://localhost:8443/' )

//=== SSL UNSECURE CERTIFICATE ===
def sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, [ new X509TrustManager() {
  public X509Certificate[] getAcceptedIssuers() {null }
  public void checkClientTrusted(X509Certificate[] certs, String authType) { }
  public void checkServerTrusted(X509Certificate[] certs, String authType) { }
} ] as TrustManager[], new SecureRandom())
def sf = new SSLSocketFactory(sslContext)
def httpsScheme = new Scheme("https", sf, 8443)
http.client.connectionManager.schemeRegistry.register( httpsScheme )

http.request( groovyx.net.http.Method.POST, groovyx.net.http.ContentType.JSON ) { req ->
    uri.path = '/a/admin/runtime/upload'
    uri.query = [ username: "username", password: "password", version: version]
    requestContentType = 'multipart/form-data'
    org.apache.http.entity.mime.MultipartEntity entity = new org.apache.http.entity.mime.MultipartEntity()
    def file = new File("file.zip")
    entity.addPart("runtimeFile", new org.apache.http.entity.mime.content.ByteArrayBody(file.getBytes(), 'file.zip'))
    req.entity = entity
}
def http = new groovyx.net.http.HTTPBuilder( 'https://www.realserver.com/' )

http.request( groovyx.net.http.Method.POST, groovyx.net.http.ContentType.JSON ) { req ->
    uri.path = '/a/admin/runtime/upload'
    uri.query = [ username: "username", password: "password" ]
    requestContentType = 'multipart/form-data'
    org.apache.http.entity.mime.MultipartEntity entity = new org.apache.http.entity.mime.MultipartEntity()
    def file = new File("file.zip")
    entity.addPart("runtimeFile", new org.apache.http.entity.mime.content.ByteArrayBody(file.getBytes(), 'file.zip'))
    req.entity = entity
}
当我运行此命令时,会出现以下错误:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

任何提示或建议都将不胜感激。

这可能是因为该服务正在使用HTTPS的自签名证书。为了正确地与它交互,应该使用keytool将它导入到JRE的cacerts文件中。示例命令如下所示:

keytool -import -alias serviceCertificate -file ServiceSelfSignedCertificate.cer -keystore {path/to/jre/lib/security/cacerts}

它不是自签名证书。正如我在问题中所述,这是通过SSL和合法购买的证书进行的。但是,此证书的根证书可能不在cacerts中,因此您必须导入它。