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

Posted

技术标签:

【中文标题】异常无法在 Spring MVC 中验证目标的证书【英文标题】:Exception unable to validate certificate of the target in spring MVC 【发布时间】:2015-11-10 03:52:27 【问题描述】:

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

那么如何验证证书

网址: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;
       

【问题讨论】:

【参考方案1】:

您面临的问题是您的应用程序无法验证您尝试连接的外部服务器,因为其证书不受信任

简而言之就是:

您的应用程序尝试通过安全 (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 工具。

【讨论】:

获取证书后如何使用它来验证服务器证书 获得证书文件后,您只需将其导入应用程序正在使用的密钥库中。找到您使用的 Java 安装,然后转到:JAVA_DIR/lib/security/cacerts。 我已包含证书并尝试进行身份验证,但我无法通过身份验证获得 401 状态,请参阅 ***.com/questions/32064672/… 状态 401 是一个不同的问题。得到这意味着您的应用级身份验证失败,但这也意味着 HTTPS 握手成功,因此本文中的问题已解决。 是的,我知道我在问你能不能解决这个问题【参考方案2】:

你可以替换

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

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

【讨论】:

【参考方案3】:

检查文件$JAVA_HOME/lib/security/cacerts是否存在! 在我的例子中,它不是一个文件,而是一个指向 /etc/ssl/certs/java/cacerts 的链接,而且这也是一个指向自身的链接(什么???),因此 JVM 无法找到该文件。

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

【讨论】:

【参考方案4】:

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

【讨论】:

以上是关于异常无法在 Spring MVC 中验证目标的证书的主要内容,如果未能解决你的问题,请参考以下文章

使用休眠验证器的 Spring mvc 表单验证

ASP.Net MVC 5 Sending Email 错误:根据验证程序,远程证书无效

在 Spring MVC 中处理 JWT 异常

OUTLOOK 无法验证安全证书问题

看到 SSLFactory 使用的密钥库了吗?异常:“sun....certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径”

无法运行我的 Spring Security MVC WebApp SpringChainFilter 抛出异常,rawPassword 不能为空