【问题标题】:How to configure Spring RestTemplate with SSL (in Spring @MVC)如何使用 SSL 配置 Spring RestTemplate(在 Spring @MVC 中)
【发布时间】:2011-12-16 08:51:52
【问题描述】:

我想用 SSL 配置我的 Spring @MVC 存根应用程序的 Spring RestTemplate 以与 REST 基础进行通信https 应用程序,部署在 Tomcat 服务器(Spring 3、Tomcat 7)上。到目前为止,我已经完成了refer this link 的工作。现在我不知道如何将这些生成的 证书Spring RestTemplate 一起使用,任何人都可以有一些想法请帮助我。谢谢。到现在为止我做过的事情,

//Spring Security 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:无法找到请求目标的有效证书路径

【问题讨论】:

    标签: spring spring-security resttemplate


    【解决方案1】:

    这是因为您调用的服务的 SSL 证书未由受信任的证书颁发机构签署。解决方法是将证书导入 JRE 的证书信任库 (cacerts)。

    1. 在浏览器中打开网址下载证书,点击锁 浏览器地址栏中的图标。
    2. 一旦你有一个 .cer 文件,执行下面的命令

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

    【讨论】:

    【解决方案2】:

    你可以用Apache HttpComponents HttpClient的HttpComponentsClientHttpRequestFactory配置RestTemplate,绝对支持SSL。

    参考:Does REST (RestTemplate) in Spring Library support HTTPS protocol?

    【讨论】:

      【解决方案3】:

      Spring Boot 的变体:

      1. 添加依赖:

         implementation 'org.apache.httpcomponents:httpclient:4.5'    
        
      2. 提供 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)上启动。 或者,您可以使用my spring boot starter

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 2021-04-25
          • 1970-01-01
          • 2016-09-07
          • 1970-01-01
          • 1970-01-01
          • 2016-08-22
          • 2015-05-05
          • 1970-01-01
          • 2020-10-05
          相关资源
          最近更新 更多