如何在Groovy中使用自签名证书的SSL?

12

我需要访问一些使用自签名证书的SSL资源。通常,大多数工具都有一个简单的设置,允许这些资源被访问而不会出现错误或警告。然而,使用JVM正确的方法似乎是将签名证书作为CA导入到密钥库中。

我有一个Groovy脚本,我想在任何JVM上独立运行,而不需要修改密钥库或分发新的密钥库。是否有一种简单的方法可以覆盖认证验证?

2个回答

24

经过一些调查,我发现了这篇文章。这是我最终使用的代码:

import javax.net.ssl.HostnameVerifier
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

def nullTrustManager = [
    checkClientTrusted: { chain, authType ->  },
    checkServerTrusted: { chain, authType ->  },
    getAcceptedIssuers: { null }
]

def nullHostnameVerifier = [
    verify: { hostname, session -> true }
]

SSLContext sc = SSLContext.getInstance("SSL")
sc.init(null, [nullTrustManager as X509TrustManager] as TrustManager[], null)
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory())
HttpsURLConnection.setDefaultHostnameVerifier(nullHostnameVerifier as HostnameVerifier)

使用需谨慎:这会破坏证书验证!


3
一般来说,hvgotcodes是一个更好的解决方案。当然,可能会因情况而异。你的解决方案的问题在于现在所有主机都是有效的,而不仅仅是你实际想要放行的一小部分。如果你的代码受到严格控制,并且你确信只会连接到“可信”来源,那么就没问题了。但是,如果你将证书导入到信任库中,你就可以免受DNS重定向和任何其他问题的影响。如果你需要更加动态的行为,你也可以在运行时设置javax.net.ssl.trustStore属性。 - Brian M. Carr
总的来说,我同意。但在某些脚本上下文中,完全忽略证书管理是很好的选择;例如,在测试服务器动态生成且客户端密钥库需要不断保持同步的情况下。值得注意的是,其他动态语言如Ruby和Python将此作为简单的配置设置,并分别不默认强制执行证书链。 - ataylor
3
只是为了让那些复制粘贴而没有经过@BrianM.Carr评论的读者看到:这个解决方案完全禁用了证书验证步骤,从而使连接可能容易受到中间人攻击 - Bruno
1
十年过去了,答案仍然有效。不过现在需要修改 getAcceptedIssuers 方法如下:getAcceptedIssuers: { [] as java.security.cert.X509Certificate[] } - Giuseppe Ricupero

10
我刚刚在处理一个我正在开发的Grails应用程序时遇到了这个问题。您只需要处理密钥库一次。假设您已经拥有证书,只需将其放入密钥库中,然后通过命令行参数将您的jvm指向密钥库即可...
编辑 - 我不知道是否有任何方法可以绕过对密钥库的需求。但是,您可以使用所需的证书创建一个密钥库,并将其与您的应用程序一起传递。您只需要执行一次。
编辑编辑 - 这是keytool和java CL prop的命令。
keytool -import -trustcacerts -alias www.the-domain.com -file the-cert.der -keystore store.jks

-Djavax.net.ssl.trustStore=/path/to/store.jks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接