Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring security 如何配置TestRestTemplate以使用密钥库?_Spring Security_Integration Testing_Keystore_Spring Security Oauth2_Openid Connect - Fatal编程技术网

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
对象,该对象