异常无法在 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 中验证目标的证书的主要内容,如果未能解决你的问题,请参考以下文章
ASP.Net MVC 5 Sending Email 错误:根据验证程序,远程证书无效
看到 SSLFactory 使用的密钥库了吗?异常:“sun....certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径”
无法运行我的 Spring Security MVC WebApp SpringChainFilter 抛出异常,rawPassword 不能为空