Spring security 如何配置TestRestTemplate以使用密钥库?
我的项目有一系列使用Spring security 如何配置TestRestTemplate以使用密钥库?,spring-security,integration-testing,keystore,spring-security-oauth2,openid-connect,Spring Security,Integration Testing,Keystore,Spring Security Oauth2,Openid Connect,我的项目有一系列使用testrestemplate和MockMvc的集成测试。这些都顺利通过了 现在,我已经将springbootstartersecurity和springsecurityoauth2autoconfigure依赖项添加到我的项目中。我添加了一个自定义类,该类扩展了websecurityConfigureAdapter,允许对我的应用程序进行开放访问(目前)。这是上课时间 @Configuration @EnableWebSecurity @EnableGlobalMethod
testrestemplate
和MockMvc
的集成测试。这些都顺利通过了
现在,我已经将springbootstartersecurity
和springsecurityoauth2autoconfigure
依赖项添加到我的项目中。我添加了一个自定义类,该类扩展了websecurityConfigureAdapter
,允许对我的应用程序进行开放访问(目前)。这是上课时间
@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资源服务器
,因此我还使用@enableSourceServer
注释了我的主类。在运行应用程序时,我将可信密钥存储的路径作为运行参数提供<代码>-Djavax.net.ssl.trustStore=-Djavax.net.ssl.trustStorePassword=
应用程序运行良好,但现在所有的集成测试都失败了。下面是使用testrestemplate
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
无法获取用户详细信息:class org.springframework.web.client.ResourceAccessException,获取请求时发生I/O错误,用于:
PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:
找不到请求目标的有效证书路径;嵌套异常为javax.net.ssl.SSLHandshakeException:
PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:找不到请求目标的有效证书路径
似乎需要指示我用于测试的
testrestemplate
使用与应用程序相同的密钥库。有可能这样做吗?对于MockMvc
,它将如何工作?我认为您可能还需要传递-Djavax.net.ssl.trustStore=-Djavax.net.ssl.trustStorePassword=
运行测试时的参数。
对于在configuration和maven中运行单测试传递参数,您也可以传递这些参数
下面两个链接可能会有所帮助
谢谢,你发布的第一个链接非常有用。这是我的RestTemplate工作代码,它接受任何证书,如果其他人认为它有用的话。它仍然依赖于提供的有效令牌,但这是另一回事
private RestTemplate buildRestTemplate() throws Exception {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(
new TrustSelfSignedStrategy()
).build();
SSLConnectionSocketFactory socketFactory =
new SSLConnectionSocketFactory(sslContext);
HttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(socketFactory).build();
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
弹簧靴2的解决方案
下面的答案旨在针对Spring Boot 2进行开发,并使用自签名证书进行开发(推荐用于生产的适当证书-请参阅)
您可以使用keytool
命令创建包含自签名证书的密钥库文件:-
keytool -genkey -storetype PKCS12 \
-alias selfsigned_localhost_sslserver \
-keyalg RSA -keysize 2048 -validity 3650 \
-dname "CN=localhost, OU=Engineering, O=Acme Corp, L=New York, S=New York, C=US" \
-noprompt -keypass changeit -storepass changeit \
-keystore keystore-self-signed.p12
keystore self-signed.p12
文件将包含一个自签名证书,该文件可以移动到src/main/resources
文件夹(或者src/test/resources
,如果您愿意)
将以下内容添加到您的应用程序.yaml
Spring配置中以使用SSL并指向密钥库:-
服务器:
港口:443
ssl:
已启用:true
密钥存储:类路径:keystore-self-signed.p12
密钥存储类型:PKCS12
协议:TLS
启用的协议:TLSv1.2#最佳实践-请参阅https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices
密钥密码:changeit
密钥存储密码:changeit
让我们创建一个超级简单的Spring引导控制器端点来测试:-
@RestController
公共类PingController{
@GetMapping(“/ping”)
公众反应平(){
返回新的响应属性(“pong”,HttpStatus.OK);
}
}
我们现在可以使用curl
命令(或Postman)来达到这个端点,即
$curlhttps://localhost/ping --不安全——沉默
庞
注意:如果我们不包括--unsecure
,那么curl
将返回curl:(60)SSL证书问题:自签名证书
要使用testrestemplate
对其端点进行正确的Spring Boot集成测试,我们可以执行以下操作:-
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=webEnvironment.RANDOM\u端口)
公共类PingControllerTest{
@值(${server.ssl.key store}”)
私有资源密钥库;//在配置中指定的注入密钥库
@值(${server.ssl.key store password}”)
私有字符串keystrepassword;//从配置注入密码
@本地服务器端口
受保护的int-port;//在运行时随机选取服务器端口
私有TestRestTemplate;
@以前
public void setup()引发异常{
SSLContext SSLContext=新的SSLContextBuilder()
.装载信任材料(
keyStore.getURL(),
keystrepassword.toCharArray()
).build();
SSLConnectionSocketFactory socketFactory=新的SSLConnectionSocketFactory(sslContext);
HttpClient HttpClient=HttpClients.custom().setsslssocketfactory(socketFactory.build();
HttpComponents客户端HttpRequestFactory工厂=新的HttpComponents客户端HttpRequestFactory(
httpClient);
RestTemplateBuilder rtb=新的RestTemplateBuilder()
.requestFactory(()->factory)
.rootUri(“https://localhost:“+港口);
this.restTemplate=新的TestRestTemplate(rtb,null,null,HttpClientOption.SSL);
}
@试验
公营部门{
ResponseEntity结果=restemplate.getForEntity(“/ping”,String.class);
assertEquals(HttpStatus.OK,result.getStatusCode());
assertEquals(“pong”,result.getBody());
}
}
如您所见,setup
方法创建了SSLContext
对象的实例,该对象加载(并“信任”)密钥库自签名.p12文件中的自签名证书(通过Spring资源
对象注入)
SSLContext
类被注入一个SSLConnectionSocketFactory
对象,该对象又被注入一个HttpClient
对象,该对象