繁体   English   中英

Spring 引导 + OAuth2 + REST API - 找不到证书路径

[英]Spring Boot + OAuth2 + REST API - Certification Path Not Found

我正在现有的 Spring Boot v2.1.4 应用程序中实现 RESTful API。 该应用程序包含一个 Spring MVC 层,该层使用 Spring 安全性进行保护。 有使用 JSP 构建的视图。 一些 JSP 嵌入了客户端脚本,这些脚本调用 AJAX 调用来检索信息。 这些调用将针对 API 而不是现有的 MVC 端点执行。

新服务端点使用 OAuth2 进行保护,并且已在应用程序中设置授权服务器并使用 @EnableAuthorizationServer 注释激活。 为了在这些端点上启用 SSL,我使用 keytool 生成了一个私钥/公钥对。

keytool -genkeypair -alias apitest -keyalg RSA -validity 365 -keysize 2048 -keystore apitest.jks

然后我执行以下命令来导出自签名证书。

keytool -export -alias apitest -keystore apitest.jks -rfc -file apitest.cer

我已将证书添加到信任库文件中,当应用程序启动时,该文件的路径和密码将加载到系统属性中。

System.setProperty("javax.net.ssl.trustStore", truststorePath);
System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword);

由于 MVC 层由 Spring Security 保护,因此当用户成功登录应用程序后,我尝试从令牌端点检索 OAuth2 令牌。 令牌作为 cookie 在响应中返回(此处未显示)。

ResourceOwnerPasswordAccessTokenProvider provider = new ResourceOwnerPasswordAccessTokenProvider();
ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setClientAuthenticationScheme(AuthenticationScheme.none);
UriComponents uriComponents = ServletUriComponentsBuilder.fromServletMapping(request).path("/oauth/token").build();
resource.setAccessTokenUri(uriComponents.toUriString());
resource.setScope(Arrays.asList("read", "write"));
resource.setClientId(oAuth2ClientDetails.getClientId());
resource.setClientSecret(oAuth2ClientDetails.getClientSecret());
resource.setGrantType("password");
resource.setUsername(userName);
resource.setPassword(userCredentials);
OAuth2AccessToken accessToken = provider.obtainAccessToken(resource, new DefaultAccessTokenRequest());
return accessToken.getValue();

当此逻辑触发对令牌端点的调用时,会观察到以下错误。

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://localhost:8443/testapp/oauth/token": 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
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:744) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:579) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]

由于 API 端点和授权服务器都在本地主机上运行,我认为信任库文件中的自签名证书就足够了。 我缺少什么来完成这个设置?

我怀疑您的问题可能与没有父根权限的证书有关。 我通常推荐使用信任链创建现实世界自签名证书的方法:

  • 首先创建根证书颁发机构
  • 然后使用它来创建服务器 SSL 证书

根权限

对于使用 OAuth 进行本地开发,我创建了一个名为 mycompany.ca.crt 的根权限,然后像这样添加 Java 信任,并将此证书分发给浏览器:

  • keytool -keystore cacerts -storepass changeit -importcert -alias mycompanyca -file ~/Desktop/mycompany.ca.crt

创建 SSL 证书

然后我使用根证书创建 SSL 证书,不需要额外的信任配置。

脚本

如果有兴趣,看看我的这些脚本,它们使用 openssl 工具:

  • makeCerts.ps1 脚本适用于 Windows
  • makeCerts.sh 脚本适用于 MacOS 或 Linux
  • 运行脚本时会创建其他文件
  • 您需要编辑域名以匹配您正在使用的域名

我的示例使用用于本地 PC 开发的通配符域,并且我还将域添加到我的主机文件中。 在浏览器客户端中,我看到了这个:

在此处输入图像描述

尽管根据您的问题,我怀疑您已经知道其中的大部分内容,但我的博客文章中的更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM