上一篇文章已经通过配置RestTemplate,完成了后台客户端以https方式对服务端接口的访问。本篇作为补充说明,介绍一下如果在没有证书的情况下,绕过SSL证书的校验。

配置步骤如下:

一. 从JDK证书管理库删除原证书(非必须),如果未导入过证书请忽略此步

查看证书命令:keytool -list -storepass changeit  -keystore "C:/Program Files/Java/jdk1.8.0_131/jre/lib/security/cacerts"|findstr testhttps

删除证书命令:keytool -delete -alias testhttps  -storepass changeit -keystore "C:/Program Files/Java/jdk1.8.0_131/jre/lib/security/cacerts"

二. 添加相应代码

  1. 忽略ssl证书校验类

import org.apache.http.client.HttpClient;
import org.springframework.http.client.SimpleClientHttpRequestFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * 绕过证书
 */
public class IgnoreSSLRequestFactory extends SimpleClientHttpRequestFactory {

    public IgnoreSSLRequestFactory(HttpClient httpClient) {
        super();
    }

    @Override
    protected void prepareConnection(HttpURLConnection connection, String httpMethod)
            throws IOException {
        if (connection instanceof HttpsURLConnection) {
            prepareHttpsConnection((HttpsURLConnection) connection);
        }
        connection.setConnectTimeout(3000);
        connection.setReadTimeout(3000);
        super.prepareConnection(connection, httpMethod);
    }

    private void prepareHttpsConnection(HttpsURLConnection connection) {
        connection.setHostnameVerifier(new SkipHostnameVerifier());
        try {
            connection.setSSLSocketFactory(createSslSocketFactory());
        } catch (Exception ex) {
            // Ignore
        }
    }

    private SSLSocketFactory createSslSocketFactory() throws Exception {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, new TrustManager[]{new SkipX509TrustManager()},
                new SecureRandom());
        return context.getSocketFactory();
    }

    private class SkipHostnameVerifier implements HostnameVerifier {

        @Override
        public boolean verify(String s, SSLSession sslSession) {
            return true;
        }

    }

    private static class SkipX509TrustManager implements X509TrustManager {


        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
}

  2. 编写RestTemplate配置类

import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

/**
 * restTemplate配置
 */
@Configuration
public class RestTemplateConfig {

    /**
     * 使用ssl对证书进行验证,需要将证书导出到jdk管理仓库,
     * 命令:keytool -import -v -trustcacerts -alias mytest -file "D:/tmp/mytest.cer"  -keystore "C:/Program Files/Java/jdk1.8.0_131/jre/lib/security/cacerts"
     */
    @Bean("restTemplate")
    @Primary
    public RestTemplate restTemplate() throws NoSuchAlgorithmException, KeyManagementException {
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new
                HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(6 * 1000); //获取连接池连接的超时时间(毫秒)
        httpRequestFactory.setConnectTimeout(6 * 1000);  //连接上服务器(握手成功)的时间(毫秒)
        httpRequestFactory.setReadTimeout(60 * 1000); //返回数据时间(毫秒)
        httpRequestFactory.setHttpClient(httpClient());
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
        return restTemplate;
    }

    /**
     * 绕过ssl对证书进行验证,无需将证书导出到jdk管理仓库
     */
    @Bean("restTemplateIgnoreSSL")
    public RestTemplate restTemplateIgnoreSSL() throws NoSuchAlgorithmException, KeyManagementException {
        IgnoreSSLRequestFactory requestFactory = new IgnoreSSLRequestFactory(httpClient());
        requestFactory.setConnectTimeout(60000); //连接上服务器(握手成功)的时间
        requestFactory.setReadTimeout(60000); //返回数据时间
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        return restTemplate;
    }

    @Bean
    public HttpClient httpClient() throws KeyManagementException, NoSuchAlgorithmException {
        SSLContextBuilder contextBuilder = new SSLContextBuilder();
        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(contextBuilder.build(), NoopHostnameVerifier.INSTANCE);
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", socketFactory).build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(200);
        connectionManager.setDefaultMaxPerRoute(100);
        CloseableHttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();
        return httpClient;
    }

  3. 编写Controller 控制类

import com.ssl.demo.entity.UserInfo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
public class UserController {

    /**
     * 使用https访问接口
     */
    @Resource(name = "restTemplate")
    private RestTemplate restTemplate;

    /**
     * 使用https访问接口,并忽略ssl证书验证
     */
    @Resource(name = "restTemplateIgnoreSSL")
    private RestTemplate restTemplateIgnoreSSL;

    @RequestMapping("getUserInfo")
    public UserInfo getUserInfo() {
        UserInfo data = restTemplate.getForObject("https://localhost:9090/ssl-service/getUserInfo", UserInfo.class);
        return data;
    }

    @RequestMapping("getUserInfoIgnoreSSL")
    public UserInfo getUserInfoIgnoreSSL() {
        UserInfo data = restTemplateIgnoreSSL.getForObject("https://localhost:9090/ssl-service/getUserInfo", UserInfo.class);
        return data;
    }

}

 四. 验证结果

在浏览器访问:http://localhost:8080/ssl-client/getUserInfoIgnoreSSL

 至此完成了忽略SSL验证的配置和验证。

完整示例下载地址(同上一篇文章):

链接:https://pan.baidu.com/s/1xrfxkbnz1bGhhrTKKKhPew 

提取码:tyoe

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐