使用RestTemplate访问https实现SSL请求操作

目录
  • 1、添加HttpsClientRequestFactory工具类
  • 2、修改RestTemplate
  • 3、访问https,抛出的异常
    • 方案一:替换jce包
    • 方案二:升级 JDK到1.8版本(推荐方式)

方法1: 用java生成证书,不建议,移植性差。

方法2: 将RestTemplate改为https请求。

1、添加HttpsClientRequestFactory工具类

import org.springframework.http.client.SimpleClientHttpRequestFactory;
import javax.net.ssl.*;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Socket;
import java.security.cert.X509Certificate;

/**
 * TLS的三个作用:
 * 	(1)身份认证
 * 		通过证书认证来确认对方的身份,防止中间人攻击
 * 	(2)数据私密性
 * 		使用对称性密钥加密传输的数据,由于密钥只有客户端/服务端有,其他人无法窥探。
 * 	(3)数据完整性
 * 		使用摘要算法对报文进行计算,收到消息后校验该值防止数据被篡改或丢失。
 *
 *     使用RestTemplate进行HTTPS请求访问:
 * 	private static RestTemplate restTemplate = new RestTemplate(new HttpsClientRequestFactory());
 *
 */
public class HttpsClientRequestFactory extends SimpleClientHttpRequestFactory {
    @Override
    protected void prepareConnection(HttpURLConnection connection, String httpMethod) {
        try {
            if (!(connection instanceof HttpsURLConnection)) {
                throw new RuntimeException("An instance of HttpsURLConnection is expected");
            }

            HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        @Override
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        }
                        @Override
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        }
                    }
            };
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            httpsConnection.setSSLSocketFactory(new MyCustomSSLSocketFactory(sslContext.getSocketFactory()));

            httpsConnection.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });

            super.prepareConnection(httpsConnection, httpMethod);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static class MyCustomSSLSocketFactory extends SSLSocketFactory {
        private final SSLSocketFactory delegate;
        public MyCustomSSLSocketFactory(SSLSocketFactory delegate) {
            this.delegate = delegate;
        }

        // 返回默认启用的密码套件。除非一个列表启用,对SSL连接的握手会使用这些密码套件。
        // 这些默认的服务的最低质量要求保密保护和服务器身份验证
        @Override
        public String[] getDefaultCipherSuites() {
            return delegate.getDefaultCipherSuites();
        }

        // 返回的密码套件可用于SSL连接启用的名字
        @Override
        public String[] getSupportedCipherSuites() {
            return delegate.getSupportedCipherSuites();
        } 

        @Override
        public Socket createSocket(final Socket socket, final String host, final int port,
                                   final boolean autoClose) throws IOException {
            final Socket underlyingSocket = delegate.createSocket(socket, host, port, autoClose);
            return overrideProtocol(underlyingSocket);
        } 

        @Override
        public Socket createSocket(final String host, final int port) throws IOException {
            final Socket underlyingSocket = delegate.createSocket(host, port);
            return overrideProtocol(underlyingSocket);
        }

        @Override
        public Socket createSocket(final String host, final int port, final InetAddress localAddress,
                                   final int localPort) throws
                IOException {
            final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort);
            return overrideProtocol(underlyingSocket);
        }

        @Override
        public Socket createSocket(final InetAddress host, final int port) throws IOException {
            final Socket underlyingSocket = delegate.createSocket(host, port);
            return overrideProtocol(underlyingSocket);
        }

        @Override
        public Socket createSocket(final InetAddress host, final int port, final InetAddress localAddress,
                                   final int localPort) throws
                IOException {
            final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort);
            return overrideProtocol(underlyingSocket);
        }

        private Socket overrideProtocol(final Socket socket) {
            if (!(socket instanceof SSLSocket)) {
                throw new RuntimeException("An instance of SSLSocket is expected");
            }
            //((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"});
            ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"});
            return socket;
        }
    }
}

注意:服务端TLS版本要和客户端工具类中定义的一致。(TLSv1.2)

2、修改RestTemplate

在使用的时候,将

private static RestTemplate restTemplate = new RestTemplate();

改为:

private static RestTemplate restTemplate = new RestTemplate(new HttpsClientRequestFactory());

其他代码不变。

也可使用注入的方式:

@Configuration
public class ConfigBean {
 @Bean
 public RestTemplate getRestTemplate() {
  return new RestTemplate(new HttpsClientRequestFactory());
 }
}

3、访问https,抛出的异常

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure解决方案

因为jdk中jce的安全机制导致报的错,需要去oracle官网下载对应的jce包替换jdk中的jce包。

方案一:替换jce包

目录 %JAVA_HOME%\jre\lib\security里的local_policy.jar,US_export_policy.jar
JDK7 http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8 http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

// pub1:/home/myron/jdk1.7.0_80 % cd $JAVA_HOME/jre/lib/security/  //jce所在jdk的路径
US_export_policy.jar
local_policy.jar

方案二:升级 JDK到1.8版本(推荐方式)

// pub1:/home/myron % vi .cshrc
setenv JAVA_HOME /home/myron/jdk1.8.0_211
// pub1:/home/myron % source .cshrc
// pub1:/home/myron % java -version
java version "1.8.0_211"

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java 调用Restful API接口的几种方式(HTTPS)

    摘要:最近有一个需求,为客户提供一些Restful API 接口,QA使用postman进行测试,但是postman的测试接口与java调用的相似但并不相同,于是想自己写一个程序去测试Restful API接口,由于使用的是HTTPS,所以还要考虑到对于HTTPS的处理.由于我也是首次使用Java调用restful接口,所以还要研究一番,自然也是查阅了一些资料. 分析:这个问题与模块之间的调用不同,比如我有两个模块front end 和back end,front end提供前台展示,back

  • Spring学习笔记之RestTemplate使用小结

    前言 作为一个Java后端,需要通过HTTP请求其他的网络资源可以说是一个比较常见的case了:一般怎么做呢? 可能大部分的小伙伴直接捞起Apache的HttpClient开始做,或者用其他的一些知名的开源库如OkHttp, 当然原生的HttpURLConnection也是没问题的 本篇博文则主要关注点放在Sprig的生态下,利用RestTemplate来发起Http请求的使用姿势 I. RestTempalate 基本使用 0. 目标 在介绍如何使用RestTemplate之前,我们先抛出一些

  • Spring RestTemplate具体使用详解

    1.什么是REST? REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格的名词.REST定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的Web 服务,包括使用不同语言编写的客户端如何通过 HTTP处理和传输资源状态. 为什么称为 REST?Web本质上由各种各样的资源组成,资源由URI 唯一标识.浏览器(或者任何其它类似于浏览器的应用程序)将展示出该资源的一种表现方式,或者一种表现状态.如果用户在该页

  • 浅谈HttpClient、okhttp和RestTemplate的区别

    一.HttpClient 1.pom依赖 <!--HttpClient--> <dependency> <groupId>commons-httpclient</groupId> <artifactId>commons-httpclient</artifactId> <version>3.1</version> </dependency> 2.HttpClient代码实现 public class

  • 使用RestTemplate访问https实现SSL请求操作

    目录 1.添加HttpsClientRequestFactory工具类 2.修改RestTemplate 3.访问https,抛出的异常 方案一:替换jce包 方案二:升级 JDK到1.8版本(推荐方式) 方法1: 用java生成证书,不建议,移植性差. 方法2: 将RestTemplate改为https请求. 1.添加HttpsClientRequestFactory工具类 import org.springframework.http.client.SimpleClientHttpReque

  • 使用RestTemplate调用https接口跳过证书验证

    目录 RestTemplate调用https接口跳过证书验证 RestTemplate访问https遇到SSL证书验证错误 添加Https证书 下载证书 导入证书 生成keystore文件 项目中配置 RestTemplate调用https接口跳过证书验证 import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net

  • RestTemplate添加HTTPS证书全过程解析

    目录 RestTemplate添加HTTPS证书 证书的下载 证书导入JDK 生成keystore文件 项目中配置 RestTemplate访问HTTPS maven 配置 验证 RestTemplate添加HTTPS证书 证书的下载 先通过浏览器将未签名验证的证书保存到本地, 点击 不安全–> 证书–> 详细信息 --> 复制到文件 然后默认选择 起一个文件名 , 保存即可, 比如我将证书保存在了桌面 , 命名为 xx.cer 证书导入JDK 若是想要在项目中用到证书 , 需要先将证书

  • Java如何实现通过证书访问Https请求

    目录 Java通过证书访问Https请求 创建证书管理器类 调用测试 工具类 https请求绕过证书检测 Java通过证书访问Https请求 创建证书管理器类 import java.io.FileInputStream; import java.security.KeyStore; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net

  • Java如何跳过https的ssl证书验证详解

    打开我们首页,明显看到链接是https打头,https和http的通信协议差别,在于https安全性更高: http和https的差别 很明显,二者最大的区别在于https多了一个ssl证书验证,可以说https是身披SSL外壳的http.因为http存在如下缺陷: 1)通信使用明文,内容可能被窃听(重要密码泄露) 2)不验证通信方身份,有可能遭遇伪装(跨站点请求伪造) 3)无法证明报文的完整性,有可能已遭篡改(运营商劫持) 而https是利用SSL/TLS建立全信道,加密数据包.HTTPS使用

  • 如何使用Spring RestTemplate访问restful服务

    一. 什么是RestTemplate Spring's central class for synchronous client-side HTTP access. It simplifies communication with HTTP servers, and enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs(with possible tem

  • 详解NGINX访问https跳转到http的解决方法

    问题:浏览器打开https://www.jb51.net/aaa.html,然后跳转到http://www.jb51.net/aaa.html 网站架构:用户--https--->nginx代理---http---->tomcat/nginx+php nginx待遇发给后端的请求是http协议,后端程序跳转获取到的协议是http,返回一个redirect(http header中带Location:http://www.jb51.net/aaa.html),浏览器收到location,跳转到了

  • 微信小程序设置全局请求URL及封装wx.request请求操作示例

    本文实例讲述了微信小程序设置全局请求URL及封装wx.request请求操作.分享给大家供大家参考,具体如下: app.js: App({ //设置全局请求URL globalData:{ URL: 'https://www.oyhdo.com', }, /** * 封装wx.request请求 * method: 请求方式 * url: 请求地址 * data: 要传递的参数 * callback: 请求成功回调函数 * errFun: 请求失败回调函数 **/ wxRequest(metho

  • Laravel框架处理用户的请求操作详解

    本文实例讲述了Laravel框架处理用户的请求操作.分享给大家供大家参考,具体如下: 1.请求对象Request Request中包含了用户请求的一些信息,使用该对象首先需要use Illuminate\Http\Request类,之后在参数中传入该对象, public static function getRequest(Request $request) { //获取请求类型 echo "请求类型" . $request->method() . "<br/&g

  • Laravel5.1 框架Request请求操作常见用法实例分析

    本文实例讲述了Laravel5.1 框架Request请求操作常见用法.分享给大家供大家参考,具体如下: 这篇主要说说Request 每当用户访问我们的网站功能时都会用到它 我们可以使用Request中的一些数据来做出适当的相应. 1 常用的属性和方法 我们可以从Request中取到一些重要属性来做一些逻辑处理,下面是Request中常用的属性: 1.1 获取用户输入 (前提工作 创建一个RESTful风格的控制器 并声明路由),Request可以获取到用户输入的数据 我们来看看 1.1.1 i

随机推荐