如何使用 SSL 配置 Spring RestTemplate(在 Spring @MVC 中)

发布于 2024-12-11 22:13:18 字数 3578 浏览 0 评论 0原文

我想使用 SSL 配置我的 Spring @MVC 存根应用程序的 Spring RestTemplate,以便与 REST 基础 进行通信https 应用程序,部署在 Tomcat 服务器(Spring 3、Tomcat 7)上。到目前为止,我已经通过 参考此链接。现在我不知道如何使用这些生成的证书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=科伦坡、S=韦斯滕、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 >客户端证书 F:\jdk1.6.0_23\bin>keytool -export -alias serverKey -rfc -keystore keystore_server > server.cert

//导入证书到对应的truststore:

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 error: sun.security.validator.ValidatorException :PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径;嵌套异常是 javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径

I want to configure my Spring @MVC stub application's Spring RestTemplate with SSL for communicate to REST base https application, that deployed on Tomcat server (Spring 3, Tomcat 7). I have done up to now my works by refer this link. Now I have not any idea how to use these generated certificates with Spring RestTemplate, Can anyone have some idea please help me. Thanks. Up to now things I have done,

//Spring Security xml Configurations

   <http>
    <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>      
    <http-basic/></http> 

//Configurations for enable SSL with Tomcat

<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"/>

For generating Keys, certificates etc,

//Generate client and server keys:

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"

//Generate client and server certificates:

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

//Import certificates to corresponding truststores:

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 configurations

<!--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 going to access

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

//Exception currently I got:

org.springframework.web.client.ResourceAccessException: I/O error: sun.security.validator.ValidatorException: 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: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

挖鼻大婶 2024-12-18 22:13:18

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

  1. 通过在浏览器中打开 URL 下载证书,单击锁定
    浏览器地址栏中的图标。
  2. 获得 .cer 文件后,执行以下命令

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

This is because SSL certificate of the service you are calling is not signed by a trusted certificate authority. The workaround is to import the certificate into the certificate trust store (cacerts) of your JRE.

  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
    
大海や 2024-12-18 22:13:18

Spring Boot 的变体:

  1. 添加依赖项:

     实现 '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) 上启动。
或者,您可以使用 我的 spring boot starter

Variant for 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. Provide required SSL properties in your application.properties or application.yaml file:
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

That's it. Now you can see your Tomcat is starting on 8080 (or another port) (https).
Alternatively, you can use my spring boot starter

绝情姑娘 2024-12-18 22:13:18

您可以使用 Apache HttpComponents HttpClient 中的 HttpComponentsClientHttpRequestFactory 配置 RestTemplate,这绝对是支持 SSL。

ref: Spring 库中的 REST (RestTemplate) 是否支持 HTTPS 协议?

You can configure the RestTemplate with the HttpComponentsClientHttpRequestFactory from Apache HttpComponents HttpClient, which definitely supports SSL.

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

幸福%小乖 2024-12-18 22:13:18

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

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

You can set a couple of system properties to select the truststore used in clients

    System.setProperty("javax.net.ssl.trustStorePassword", "mypassword");
    System.setProperty("javax.net.ssl.keyStoreType", "jks");
    System.setProperty("javax.net.ssl.trustStore", "truststore_client");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文