【问题标题】:grails - RestClientBuildergrails - RestClientBuilder
【发布时间】:2014-04-22 17:52:42
【问题描述】:

我正在使用当前版本的 REST 客户端构建器插件。我通过 curl 测试了 uri:

curl --user username:password https://localhost:8085/rest/api/latest/plan.json?os_authType=basic

我得到了预期的 json 作为回报。当我尝试使用这样的插件将其翻译成 grails 时:

RestBuilder rb = new RestBuilder()
    def response = rb.get("https://localhost:8085/rest/api/latest/plan.json?os_authType=basic"){     
            auth 'username', 'password'
        }

response.json instanceof JSONObject

我收到此错误:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is 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

为什么它在 curl 中工作而不是在插件中工作?我如何让它发挥作用?

谢谢!

【问题讨论】:

  • 谁在使用 Http 而不是 https ?

标签: rest grails curl


【解决方案1】:

您需要将根证书添加到受信任证书的存储中。

http://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html


将证书作为可信证书导入

在您可以授予签名代码读取指定文件的权限之前,您需要将 Susan 的证书作为可信证书导入您的密钥库中。

假设你收到了来自苏珊的消息

  • 签名的 JAR 文件 sCount.jar,其中包含 Count.class 文件,以及
  • 文件Example.cer,其中包含与用于签署JAR 文件的私钥对应的公钥的公钥证书。

即使您创建了这些文件并且它们实际上并没有被传送到任何地方,您也可以模拟创建者和发送者 Susan 之外的其他人。假装你现在是雷。作为 Ray,您将创建一个名为 exampleraystore 的密钥库,并使用它将证书导入到别名为 susan 的条目中。

只要您使用keytool 命令指定一个尚不存在的密钥库,就会创建一个密钥库。因此,我们可以创建exampleraystore 并通过单个keytool 命令导入证书。在命令窗口中执行以下操作。

  1. 转到包含公钥证书文件Example.cer 的目录。 (实际上您应该已经在那里了,因为本课假定您始终在一个目录中。)
  2. 在一行中键入以下命令:

    keytool -import -alias susan -file Example.cer -keystore exampleraystore

由于密钥库尚不存在,它将被创建,并提示您输入密钥库密码;输入你想要的任何密码。

keytool 命令将打印出证书信息并要求您进行验证,例如,将显示的证书指纹与从另一个(可信)信息源获得的指纹进行比较。 (每个指纹都是一个相对较短的数字,可以唯一可靠地识别证书。)例如,在现实世界中,您可能会打电话给 Susan 并询问她的指纹应该是什么。她可以通过执行命令获取她创建的Example.cer文件的指纹

keytool -printcert -file Example.cer

如果她看到的指纹和keytool报告给你的指纹一样,说明证书在传输过程中没有被修改过。在这种情况下,您让keytool 继续在密钥库中放置一个受信任的证书条目。该条目包含来自文件Example.cer 的公钥证书数据,并被分配了别名susan

【讨论】:

    【解决方案2】:

    您可以禁用 RestBuilder 的 SSL 检查。

    查看代码示例:

    static Scheme disableSSLCheck() {
    
            def sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, [new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}
    
                public void checkServerTrusted(X509Certificate[] certs, String authType) {}
    
                @Override
                X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0]
                }
            }] as TrustManager[], new SecureRandom())
            def sf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
            def httpsScheme = new Scheme("https", sf, 443)
            httpsScheme
    
        }
    

    并将这个 Scheme 注册到 RestClient:

    Scheme httpsScheme = disableSSLCheck()
    restClient.client.connectionManager.schemeRegistry.register(httpsScheme)
    

    【讨论】:

      【解决方案3】:

      Mb 为时已晚,但请看这里。 https://gist.github.com/thomastaylor312/80fcb016020e4115aa64320b98fb0017

      我在集成测试中确实将它作为单独的方法

       def static disableSSLCheck() {
          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)
      }
      

      然后就

      void "test authentication"(){
          given:
          String url = "j_spring_security_check"
          MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>()
          form.add("grant_type", "password")
          form.add("j_username", "vadim@ondeviceresearch.com")
          form.add("j_password", "notSecure")
          form.add("_spring_security_remember_me", "true")
          //TODO SET username and pass
          //todo get token back
          disableSSLCheck()
          when:
          RestResponse response = rest.post(host + url){
              accept("application/json")
              contentType("application/x-www-form-urlencoded")
              body(form)
          }
          response
          then:
          response.status == 200
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-17
        • 2012-09-08
        相关资源
        最近更新 更多