如何在Spring @MVC中配置带SSL的RestTemplate

11
我想配置我的Spring @MVC stub应用程序的Spring RestTemplate,以通过SSL与部署在Tomcat服务器上的REST基础https应用程序进行通信(Spring 3,Tomcat 7)。到目前为止,我已经完成了我的工作请参考此链接。现在我不知道如何使用这些生成的证书与Spring RestTemplate,有没有人有一些想法可以帮助我。谢谢。到目前为止,我所做的事情是:
//Spring安全性xml配置
   <http>
    <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>      
    <http-basic/></http> 

//配置Tomcat启用SSL

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="200"
    scheme="https" secure="true" SSLEnabled="true"
    keystoreFile="C:\Users\Channa\.keystore" keystorePass="changeit"
    clientAuth="false" sslProtocol="TLS"/>

生成密钥、证书等内容,

//生成客户端和服务器密钥:

F:\jdk1.6.0_23\bin>keytool -genkey -keystore keystore_client -alias clientKey -dname "CN=localhost, OU=Dev, O=MyBusiness, L=Colombo, S=Westen, C=SL"
F:\jdk1.6.0_23\bin>keytool -genkey -keystore keystore_server -alias serverKey -dname "CN=localhost, OU=Dev, O=MyBusiness, L=Colombo, S=Westen, C=SL"

//生成客户端和服务器证书:

F:\jdk1.6.0_23\bin>keytool -export -alias clientKey -rfc -keystore keystore_client > client.cert F:\jdk1.6.0_23\bin>keytool -export -alias serverKey -rfc -keystore keystore_server > server.cert

//将证书导入到相应的信任库中:

F:\jdk1.6.0_23\bin>keytool -import -alias clientCert -file client.cert -keystore truststore_server F:\jdk1.6.0_23\bin>keytool -import -alias serverCert -file server.cert -keystore truststore_client

//Spring RestTemplate配置

<!--Http client-->
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
    <constructor-arg ref="httpClientParams"/>
    <property name="state" ref="httpState"/>
</bean>

<!--Http state-->
<bean id="httpState" class="com.org.imc.test.stub.http.CustomHttpState">
    <property name="credentials" ref="usernamePasswordCredentials"/>
</bean>

<!--User name password credentials-->
<bean id="usernamePasswordCredentials" class="org.apache.commons.httpclient.UsernamePasswordCredentials"/>

<!--Http client-->
<bean id="httpClientFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
    <constructor-arg ref="httpClient"/>
</bean>

<!--RestTemplate-->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <constructor-arg ref="httpClientFactory"/>
</bean>

//将要访问的Https URL

ResponseEntity<User> rECreateUser = restTemplate.postForEntity("https://127.0.0.1:8443/skeleton-1.0/login", user, User.class);

//我目前遇到的异常:

org.springframework.web.client.ResourceAccessException: I/O错误:sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效认证路径;嵌套异常是javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效认证路径

4个回答

7

这是由于您所调用的服务的SSL证书未经受信任的证书颁发机构签名。解决方法是将证书导入到您JRE的证书信任库(cacerts)中。

  1. download the cert by opening the URL in a browser, click the lock icon in the browser's address bar.
  2. Once you have a .cer file execute the below command

    keytool -import -keystore jdk1.8.0_77/jre/lib/security/cacerts -file ~/test.cer -alias test
    

3
在不在Java级别配置的情况下,是否可能在应用服务器级别维护客户端证书? - Eranda
1
您可以将证书导入到自定义信任存储文件中,然后按照此处所述进行指定:https://dev59.com/1XI95IYBdhLWcg3w1BdN#18767045 或者您可以尝试这里描述的内容:https://dev59.com/mWw15IYBdhLWcg3wO5EH#6755459。 - Peter Szanto

4

适用于Spring Boot的变体:

  1. Add dependency:

     implementation 'org.apache.httpcomponents:httpclient:4.5'    
    
  2. Provide RestTemplate bean:

@Bean
private RestTemplate restTemplate() {
        SSLContext sslContext = buildSslContext();
        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);

        HttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(socketFactory)
                .build();

        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);

        return new RestTemplate(factory);
    }

private SSLContext buildSslContext() {
        try {
            char[] keyStorePassword = sslProperties.getKeyStorePassword();
            return new SSLContextBuilder()
                    .loadKeyMaterial(
                            KeyStore.getInstance(new File(sslProperties.getKeyStore()), keyStorePassword),
                            keyStorePassword
                    ).build();
        } catch (Exception ex) {
            throw new IllegalStateException("Unable to instantiate SSL context", ex);
        } finally {
            sslProperties.setKeyStorePassword(null);
            sslProperties.setTrustStorePassword(null);
        }
    }
  1. 在您的 application.properties 或 application.yaml 文件中提供所需的 SSL 属性:
server:
    ssl:
        enabled: true
        key-store: /path/to/key.keystore
        key-store-password: password
        key-alias: alias
        trust-store: /path/to/truststore
        trust-store-password: password

就是这样。现在你可以看到你的Tomcat正在8080端口(或其他端口)(https)上启动。 或者,您可以使用我的Spring Boot Starter


2

0

您可以设置一些系统属性来选择客户端使用的信任库

    System.setProperty("javax.net.ssl.trustStorePassword", "mypassword");
    System.setProperty("javax.net.ssl.keyStoreType", "jks");
    System.setProperty("javax.net.ssl.trustStore", "truststore_client");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接