springBoot发布https服务及调用

一、服务端发布https服务

1、准备SSL证书

(1)自签名证书:如果你只是用于开发或测试环境,可以生成一个自签名证书。

(2)CA 签名证书:对于生产环境,应该使用由受信任的证书颁发机构 (CA) 签名的证书。

这里采用生成自签名证书,可以使用keytool工具生成自签名证书(jdk工具):

复制代码
keytool -genkeypair -alias myapp -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650

这将创建一个有效期为 10 年的自签名证书,并将其存储在 keystore.p12 文件中。你需要提供一些信息,如组织名称等。注意记住密码和别名。

如下图:

2、配置springboot启用HTTPS并指定SSL证书的位置和密码

application.propertiesapplication.yml都可以。这样配置可以读取环境变量

把证书放在resource的ssl目录下

复制代码
server:
  port: 8443
  ssl:
    enabled: ${SSL_ENABLED:true}
    key-store: ${SSL_KEY_STORE:classpath:ssl/keystore.p12}
    key-store-password: ${SSL_KEY_STORE_PASSWORD:myapptest}
    keyStoreType: ${SSL_KEY_STORE_TYPE:PKCS12}
    keyAlias: ${SSL_KEY_ALIAS:myapp}

启动服务即可通过https访问了,默认可以设置成false

3、配置docker容器,启动https

把证书放在ssl目录下

复制代码
version: "3"
services:
 
  test-https:
    image: openjdk:8-jdk
    container_name: test-https
    restart: always
    ports:
      - 22443:22443
    command: java -jar /opt/test-https.jar
    volumes:
      - /home/services/test/:/opt/
      - /home/services/test/config/:/config/
      - /home/services/test/ssl/:/ssl/
      - /home/services/test/template_server/:/template_server/
      - /home/services/test/patch/:/patch/
      - /home/log/test/:/logs/
    environment:
      - TZ=Asia/Shanghai
      - SERVICE_HOST=${HOST_IP}
      - server.port=22443
      - NACOS_NAMESPACE=${NACOS_NAMESPACE}
      - NACOS_ADDR=${NACOS_ADDR}
       #开启https,如果不开启则配置为false
      - SSL_ENABLED=true
      #以下配置根据实际证书配置
      - SSL_KEY_STORE=ssl/keystore.p12
      - SSL_KEY_STORE_PASSWORD=myapptest
      - SSL_KEY_STORE_TYPE=PKCS12
      - SSL_KEY_ALIAS=myapp
      - JAVA_OPTS=-Xmx512m -XX:G1ConcRefinementThreads=4 -XX:MaxDirectMemorySize=1G

二、通过httpinvoke方法https服务

跳过证书校验

复制代码
public class HttpInvokerRequestExecutorWithSession extends SimpleHttpInvokerRequestExecutor {

	private int connectTimeout=0;

	private int readTimeout=0;


	private SSLContext sslContext;
	private HostnameVerifier hostnameVerifier;

	private void initSsl() {
		try {
			sslContext = SSLContext.getInstance("TLS");
			sslContext.init(null, new TrustManager[]{new X509TrustManager() {
				public java.security.cert.X509Certificate[] getAcceptedIssuers() {
					return null;
				}
				public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
				public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
			}}, new SecureRandom());
		} catch (KeyManagementException | NoSuchAlgorithmException e) {
			logger.error("ssl init error:",e);
			throw new MsrRuntimeException(e.getMessage());
		}
		hostnameVerifier = (hostname, session) -> true;
	}

	/**
	 *
	 * (non-Javadoc)
	 *
	 * @see org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor
	 *      #prepareConnection(java.net.HttpURLConnection, int)
	 */
	protected void prepareConnection(HttpURLConnection con, int contentLength) throws IOException {
		super.prepareConnection(con, contentLength);
		if (con instanceof HttpsURLConnection) {
			if (sslContext == null) {
				initSsl();
			}
			((HttpsURLConnection) con).setSSLSocketFactory(sslContext.getSocketFactory());
			((HttpsURLConnection) con).setHostnameVerifier(hostnameVerifier);
		}
		con.setConnectTimeout(connectTimeout);
		con.setReadTimeout(readTimeout);

	}

	/**
	 *
	 * (non-Javadoc)
	 *
	 * @see org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor
	 *      #validateResponse(org.springframework.remoting.httpinvoker.HttpInvokerClientConfiguration,
	 *      java.net.HttpURLConnection)
	 */
	protected void validateResponse(HttpInvokerClientConfiguration config, HttpURLConnection con)
			throws IOException {
		super.validateResponse(config, con);
	}

	public int getConnectTimeout() {
		return connectTimeout;
	}

	public void setConnectTimeout(int connectTimeout) {
		this.connectTimeout = connectTimeout;
	}

	public int getReadTimeout() {
		return readTimeout;
	}

	public void setReadTimeout(int readTimeout) {
		this.readTimeout = readTimeout;
	}

}

三、feign接口调用https服务

跳过证书校验。feign接口的地址还是正常配置http或https都支持

复制代码
import feign.Client;
import feign.Contract;
import feign.RequestInterceptor;
import feign.codec.ErrorDecoder;
import feign.jaxrs.JAXRSContract;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

@Configuration
public class FeignConfiguration {

    @Autowired
    private BusinessConfig businessConfig;

    /**
     * yaml中的配置未生效,暂时在配置类中配置
     */
    @Bean
    public Contract getFeignContract() {
        return new JAXRSContract();
    }

    @Bean
    public ErrorDecoder getFeignErrorDecoder() {
        return new FeignExceptionDecoder();
    }

    @Bean
    public OkHttpClient okHttpClient() {
        if(businessConfig.getRootServiceUrl() != null && businessConfig.getRootServiceUrl().contains("https")){
            try {
                TrustManager[] trustManagers = getTrustManager();
                if (trustManagers == null || trustManagers.length == 0) {
                    throw new IllegalStateException("Failed to create trust managers");
                }

                SSLSocketFactory sslSocketFactory = getSSLSocketFactory();
                if (sslSocketFactory == null) {
                    throw new IllegalStateException("Failed to initialize SSL socket factory");
                }

                return new OkHttpClient.Builder()
                        .readTimeout(60, TimeUnit.SECONDS)
                        .connectTimeout(60, TimeUnit.SECONDS)
                        .writeTimeout(120, TimeUnit.SECONDS)
                        .connectionPool(new ConnectionPool())
                        .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustManagers[0])
                        .hostnameVerifier((hostname, session) -> true)
                        .build();
            } catch (Exception e) {
                throw new RuntimeException("Failed to create OkHttpClient", e);
            }
        }
        return new OkHttpClient.Builder()
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(120, TimeUnit.SECONDS)
                .connectionPool(new ConnectionPool())
                .build();
    }

    @Bean
    public RequestInterceptor requestInterceptor() {
        return new CustomRequestInterceptor(businessConfig);
    }

    @Bean
    public Client feignClient(OkHttpClient okHttpClient) {
        return new CustomClient(new feign.okhttp.OkHttpClient(okHttpClient));
    }

    private TrustManager[] getTrustManager() {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[0];
                        }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                    }
            };
            return trustAllCerts;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private SSLSocketFactory getSSLSocketFactory() {
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, getTrustManager(), new SecureRandom());
            return sc.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
相关推荐
Asthenia041217 分钟前
面试复盘:MySQL 中多层级部门表和成员表的设计
后端
Asthenia041222 分钟前
面试复盘:单例 Bean 和 Request Bean 注解注入,程序启动会报错吗?
后端
威桑25 分钟前
HTTP/HTTPS 中 GET 请求和 POST 请求的区别与联系
网络协议·http·https
Asthenia041242 分钟前
面试复盘:Spring Boot 的核心注解及其子注解
后端
Asthenia041242 分钟前
Spring Boot 的Scope:Singleton/Prototype/Request/Session/Application/WebSocket
后端
小奏技术1 小时前
写了一个Java(mybatis plus)代码生成器,但是是GO实现的
后端
uhakadotcom1 小时前
使用PySpark与阿里云MaxCompute的简单指南
后端·面试·github
小杨4041 小时前
springboot框架项目实践应用十(拦截器+redis实现接口防刷)
spring boot·后端·架构
可乐加.糖1 小时前
Java 分布式高并发重试方案及实现
java·开发语言·spring boot·redis·分布式
猿来入此小猿2 小时前
基于SpringBoot+Vue3实现的宠物领养管理平台功能七
java·spring boot·毕业设计·宠物·宠物领养·毕业源码·免费学习