SpringBoot配置使用SSL、使用Https


1.首先去騰訊雲或者阿里雲申請免費ssl證書,以騰訊雲為例,不建議自己生成,因為沒辦法測試發布環境的效果,填寫個人信息,最后提示審核中才是申請成功,審核比較快,半小時就通過了。

 

2.下載已經通過審核的證書文件夾,解壓文件如下,根據項目選擇使用:

3.因為springboot使用的是內置tomcat,所以我這邊選擇tomcat文件,在resources目錄下導入xxx.jks

 4.接下來配置properties文件,密碼在同文件夾的keystorePass.txt中(騰訊雲)

 

 5.個人比較喜歡yml格式,簡潔直觀(阿里雲)

6.到這個時候基本配置完成,但不能使用https后就通知所有人重新保存網址,這時候就需要增加請求轉發,自動從http轉到https

   寫法一:在啟動類也就是@SpringBootApplication注解類中加上使用

/**
 * http重定向到https
 * @return
 */
@Bean
public TomcatServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
        @Override
        protected void postProcessContext(Context context) {
            SecurityConstraint constraint = new SecurityConstraint();
            constraint.setUserConstraint("CONFIDENTIAL");
            SecurityCollection collection = new SecurityCollection();
            collection.addPattern("/*");
            constraint.addCollection(collection);
            context.addConstraint(constraint);
        }
    };
    tomcat.addAdditionalTomcatConnectors(httpConnector());
    return tomcat;
}

@Bean
public Connector httpConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    connector.setScheme("http");
    //Connector監聽的http的默認端口號
    connector.setPort(8080);
    connector.setSecure(false);
    //監聽到http的端口號后轉向到的https的端口號,也就是項目配置的port
    connector.setRedirectPort(8089);
    return connector;
}

寫法二:另外新建一個配置類,加上@Configuration注解聲明

@Configuration
public class TomcatConfig {
    @Bean
    TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(){
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint constraint = new SecurityConstraint();
                constraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                constraint.addCollection(collection);
                context.addConstraint(constraint);
            }
        };
        factory.addAdditionalTomcatConnectors(createTomcatConnector());
        return factory;
    }

    private Connector createTomcatConnector() {
        Connector connector = new
                Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        connector.setPort(5001);
        connector.setSecure(false);
        connector.setRedirectPort(443);
        return connector;
    }
}

7.現在可以通過https://域名:8089/index訪問,這樣就看到熟悉的小鎖了

注意:RestTemplate設置headers,訪問https實現ssl請求參考:https://www.jianshu.com/p/beafe38428c7

application.properties配置:

 

#遠程調用uri及ssl設置
httpClientUri=https://192.168.3.110:8081
#類型
httpClientSSL.keyStoreType=JKS
#classpath下的文件名
httpClientSSL.keyFile= easyView.keystore
#證書密碼
httpClientSSL.keyPassword=xxxx

 

 

下面是自己封裝的調用方法:

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * @date 2020/11/04
 */
@Component
public class HttpsUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpsUtil.class);


    @Value("${httpClientSSL.keyStoreType}")
    private String keyStoreType;
    @Value("${httpClientSSL.keyFile}")
    private String keyFile;
    @Value("${httpClientSSL.keyPassword}")
    private String keyPassword;
    @Value("${httpClientUri}")
    private String url;

    public static final String GET = "GET";

    public static final String POST = "POST";

    public static final String PUT = "PUT";
    
    

    /**
     * RestTemplate訪問https請求
     *
     * @param data
     * @param addHeader
     * @return
     */
    public String transferRestTemplate(String path, String data, String httpMethod, Consumer<HttpHeaders> addHeader) {
        String body = null;
        try {
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            ClassPathResource resource = new ClassPathResource(keyFile);
            InputStream inputStream = new FileInputStream(resource.getFile());
            keyStore.load(inputStream,keyPassword.toCharArray());
            SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keyStore, TrustSelfSignedStrategy.INSTANCE).build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslcontext);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(socketFactory)
                    .build();
            HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpclient);
            RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
            HttpHeaders requestHeaders = new HttpHeaders();
            addHeader.accept(requestHeaders);
            requestHeaders.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> httpEntity = new HttpEntity<>(data, requestHeaders);
            ResponseEntity<String> response = null;
            switch(httpMethod){
                case HttpsUtil.GET :
                    response = restTemplate.exchange(url+ path, HttpMethod.GET, httpEntity, String.class);
                    break;
                case HttpsUtil.POST :
                    response = restTemplate.exchange(url+ path, HttpMethod.POST, httpEntity, String.class);
                    break;
                case HttpsUtil.PUT :
                    response = restTemplate.exchange(url+ path, HttpMethod.PUT, httpEntity, String.class);
                    break;
                default:
                    logger.error("非法請求方式:", new IllegalStateException(httpMethod));
            }
            if (Objects.nonNull(response)) {
                if (response.getStatusCode().is2xxSuccessful()) {
                    body = response.getBody();
                }
                logger.info("返回狀態碼: {}, 返回數據: {}", response.getStatusCodeValue(), body);
            }else {
                logger.info("response is null");
            }
        }catch (Exception e) {
            logger.error("https請求錯誤:", e);
        }
        return body;
    }

}

 

 

8.通過域名訪問失敗原因及解決辦法

  1. 域名未配置解析,去域名管理配置解析,10分鍾后通過ping 域名看是否顯示ip,顯示則解析成功!
  2. 域名未認證,去域名管理上傳個人信息進行域名實名!
  3. 域名已實名但未網站未備案,解決辦法
    1. 去進行網站實名,使用騰訊雲小程序認證進行icp備案即可!
    2. 可以通過域名訪問但必須加上自定義端口才行,不能使用8080或443等默認端口,否則提示連接已重置! 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM