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);
        }
    }

}
相关推荐
盖世英雄酱5813632 分钟前
Java 组长年终总结:靠 AI 提效 50%,25 年搞副业只赚 4k?
后端·程序员·trae
+VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue在线音乐播放系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
code bean2 小时前
Flask图片服务在不同网络接口下的路径解析问题及解决方案
后端·python·flask
+VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue律师咨询系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
努力的小郑2 小时前
2025年度总结:当我在 Cursor 里敲下 Tab 的那一刻,我知道时代变了
前端·后端·ai编程
困知勉行19853 小时前
springboot整合redis
java·spring boot·redis
颜淡慕潇3 小时前
深度解析官方 Spring Boot 稳定版本及 JDK 配套策略
java·后端·架构
Victor3563 小时前
Hibernate(28)Hibernate的级联操作是什么?
后端
Victor3563 小时前
Hibernate(27)Hibernate的查询策略是什么?
后端
中年程序员一枚3 小时前
Springboot报错Template not found For name “java/lang/Object_toString.sql
java·spring boot·python