我的项目有一系列使用TestRestTemplate
和MockMvc
的集成测试。这些测试都成功通过了。
我现在已经在我的项目中添加了Spring Boot Starter Security
和Spring Security OAuth2 Autoconfigure
依赖项。我已经添加了一个扩展WebSecurityConfigurerAdapter
的自定义类,以允许对我的应用程序进行开放访问(目前)。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.anyRequest()
.permitAll();
}
@Override
public void configure(WebSecurity webSecurity) {
webSecurity
.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**");
}
}
该应用程序还需要充当OAuth2 Resource Server
,因此我还使用@EnableResourceServer
注解了我的主类。
应用程序工作正常,但现在所有的集成测试都失败了。
Could not fetch user details: class org.springframework.web.client.ResourceAccessException, I/O error on GET request for <the path to my userinfo URL>:
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:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
似乎我在测试中使用的TestRestTemplate
需要被指示使用与应用程序相同的密钥库。是否可以做到这一点?它将如何为MockMvc
工作?
4条答案
按热度按时间voase2hg1#
Sping Boot 2解决方案
下面的答案是针对民间开发对Sping Boot 2和使用自签名证书的开发(适当的证书推荐用于生产-见https://letsencrypt.org/)。
您可以使用
keytool
命令创建包含自签名证书的密钥库文件:-keystore-self-signed.p12
文件将包含一个自签名证书,该文件可以移动到src/main/resources
文件夹(或src/test/resources
,如果您喜欢)。将以下内容添加到您的
application.yaml
Spring配置中以使用SSL并指向keystore:-让我们创建一个超级简单的Sping Boot 控制器端点来测试:-
我们现在可以使用
curl
命令(或Postman)来访问此端点,即注意:如果我们不包含
--insecure
,那么curl
将返回curl: (60) SSL certificate problem: self signed certificate
。要使用
TestRestTemplate
测试到他的端点的正确Sping Boot 集成测试,我们可以执行以下操作:-如您所见,
setup
方法创建了SSLContext
对象的示例,该示例加载(并“信任”)keystore-self-signed.p12
文件中的自签名证书(通过SpringResource
对象注入)。SSLContext
类被注入到一个SSLConnectionSocketFactory
对象中,然后再注入到一个HttpClient
对象中,然后再注入到一个HttpComponentsClientHttpRequestFactory
对象中。这个工厂对象最终被注入到
TestRestTemplate
示例中,用于shouldPing
集成测试。注意-我最初在以下代码中浪费了时间:
……但是这个回来了……
通过
TestRestTemplate
调试后,我意识到必须使用TestRestTemplate
的4参数构造器和HttpClientOption.SSL
,即但是,如果你使用的是普通的
RestTemplate
(例如,在Spring测试之外),那么下面的代码可以工作:-注意,为了改进-创建一个
@Bean
方法,它返回一个TestRestTemplate
示例。swvgeqrz2#
我认为在运行测试时,您可能还需要传递-Djavax.net.ssl.trustStore= -Djavax.net.ssl.trustStorePassword=参数。对于在配置和maven中运行单个测试传递参数,您也可以传递这些参数。
下面两个链接可能会有帮助
Specifying trust store information in spring boot application.properties
http://codeboarding.com/tag/testresttemplate/
cbwuti443#
谢谢你,你发布的第一个链接非常有用。这是我的RestTemplate工作代码,它接受任何证书,如果其他人发现它有用的话。它仍然依赖于提供的有效令牌,但这是另一个故事。
1cosmwyk4#
使用JUnit 4测试,spring-boot-starter-parent=2.3.12.RELEASE
我在使用
TestRestTemplate
测试启用SSL的Sping Boot 后端时遇到了同样的问题。当Spring服务器不使用SSL时,我基于
TestRestTemplate
的JUnit测试工作得很好。但是一旦我通过设置其属性将其配置为使用具有自签名证书的SSL:我开始收到与OP相同的例外。
经过多次尝试,我只设法获得了一个
RestTemplate
来连接到启用SSL的服务器,但这个类不像TestRestTemplate
那样处理4xx
和5xx
服务器异常,它捕获并解包它们,允许您使用调试器进行Assert或检查它们,因此如果我希望触发服务器异常的测试通过,我不得不重写它们。如果我能让
TestRestTemplate
与支持SSL的服务器一起工作,我就可以以最少的重写重用所有的JUnit测试。经过一些挖掘和调试,我发现注入到测试类中的
TestRestTemplate
有一个嵌入式RestTemplate
:但是它的
requestFactory
在默认情况下不支持SSL连接。长话短说,我没有创建一个新的
RestTemplate
,而是重用了框架在赋予它SSL连接功能后注入的那个。基本上你想:
1.将其
requestFactory
设置为启用SSL的;1.捕获其
rootURI
,如果服务器支持SSL,则将http:
替换为https:
,如果服务器不支持SSL,则将http:
替换为https:
;1.始终使用绝对URI与服务器建立连接。
下面是基本测试类的代码:
而派生的测试类应该以这种方式调用修改后的
mRestTemplate
:总之,这个解决方案给了我两全其美的效果:具有SSL连接功能的
RestTemplate
,以及与TestRestTemplate
类相同的4xx
和5xx
异常处理语义。