在Spring MVC中无法验证目标证书的异常

时间:2015-08-17 13:24:01

标签: java spring validation spring-mvc ssl

我正在尝试使用我的用户名和密码从jira服务器获取问题详细信息,但我收到ssl错误,说无法验证证书

所以如何验证证书

url:http:local / 8080 / frr / hello

获取错误:

  

嵌套异常是   org.springframework.web.client.ResourceAccessException:I / O错误   获取

的请求      

https://jira.example.com/rest/api/2/issue/id”:

     

sun.security.validator.ValidatorException:PKIX路径构建失败:   sun.security.provider.certpath.SunCertPathBuilderException:无法   找到所请求目标的有效证书路径;嵌套异常是   javax.net.ssl.SSLHandshakeException:   sun.security.validator.ValidatorException:PKIX路径构建失败:   sun.security.provider.certpath.SunCertPathBuilderException:无法   根据原因找到所请求目标的有效证书路径   sun.security.provider.certpath.SunCertPathBuilderException:无法   找到所请求目标的有效证书路径

我的Service.class代码

@Controller
public class Service{


    @RequestMapping("/hello")


     public String Data(ModelMap model){

        RestTemplate restTemplate = new RestTemplate();

        ResponseEntity<String> result = restTemplate.exchange("https://jira.example.com/rest/api/2/issue/id",  HttpMethod.GET, new HttpEntity<String>(createHeaders("username", "password")), String.class);

        model.addAttribute("message", result);


        return "helloworld";
    }

    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders createHeaders( String username, String password ){
        HttpHeaders header =  new HttpHeaders();
        String auth = username + ":" + password;
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")) );
        String base64Creds = "Basic " + new String( encodedAuth );
        header.add("Authorization", "Basic " + base64Creds);
        return header;
    }   
}

4 个答案:

答案 0 :(得分:8)

您遇到的问题是您的应用无法验证您尝试连接的外部服务器其证书不受信任

简而言之:

  • 您的应用程序尝试通过安全(HTTPS)渠道连接到Jira实例
  • 建立应用程序下载证书的安全连接
  • 应用程序通过尝试将证书追溯到已知的CA(保存在JRE证书库中)来检查证书的有效性。
  • 证书检查失败,因为证书是自签名的(最有可能)或已过期等等。

如果此Jira实例是内部部署(由您的公司托管),那么拥有自签名证书的可能性根本不大。在这种情况下,证书不是由已知的CA颁发的,因此如果您希望信任它,您需要手动注册

首先获得证书:

openssl s_client -connect jira.example.com:443 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

然后将其导入您自己的密钥库:

$JAVA_HOME/keytool -import -alias <server_name> -keystore $JAVA_HOME/lib/security/cacerts -file public.crt

注意:上面的命令适用于Unix环境。在Windows下,我建议在命令行中使用类似的openssl,但也有可用于同一目的的GUI工具。

答案 1 :(得分:0)

检查文件$JAVA_HOME/lib/security/cacerts是否存在! 在我的情况下,它不是文件,而是指向/etc/ssl/certs/java/cacerts的链接,而且这也是对其自身的链接(WHAT ???),因此由于这个原因,JVM无法找到该文件。

解决方案: 将真实的cacerts文件(我是从另一个JDK 完成的)复制到/etc/ssl/certs/java/目录中,它将解决您的问题:)

答案 2 :(得分:0)

如果按照@Gergely Bacso的指示即使在导入证书后仍然遇到证书问题,请确保已链接到IDE或在以前的命令行中链接了java.exe或javaw.exe二进制文件。运行Java应用程序是从JRE而不是JDK运行的,即使在cacerts密钥库中安装了证书,直到我意识到我使用的二进制文件来自JDK时,我仍然遇到证书错误。将路径切换到JRE之后,一切都按预期进行,因此我能够成功连接。我希望它可以节省尝试调试问题的时间。

答案 3 :(得分:-4)

您可以替换

String base64Creds = "Basic " + new String( encodedAuth );

String base64Creds = new String( encodedAuth ); //"Basic " String duplicated